from __future__ import annotations

import argparse
import csv
from io import StringIO
from pathlib import Path

import numpy as np
from matplotlib.colors import to_rgba


SCRIPT_DIR = Path(__file__).resolve().parent

DEFAULT_OUTPUT_PNG = SCRIPT_DIR / "merged_prompt_evidence_row_neurips_v10.png"
DEFAULT_OUTPUT_PDF = SCRIPT_DIR / "merged_prompt_evidence_row_neurips_v10.pdf"

# =========================
# 一、内嵌原始数据
# 作用：把作图需要的矩阵和样本摘要直接写在脚本里，保证脚本可独立运行。
# =========================

EMBEDDED_ROUTING_ACCURACY_CSV = """
1.000000, nan, nan, nan, nan, nan, nan, nan, nan, nan
0.188525, 0.807018, nan, nan, nan, nan, nan, nan, nan, nan
0.147541, 0.228070, 0.697674, nan, nan, nan, nan, nan, nan, nan
0.122951, 0.210526, 0.622093, 0.126050, nan, nan, nan, nan, nan, nan
0.122951, 0.210526, 0.610465, 0.126050, 0.047619, nan, nan, nan, nan, nan
0.114754, 0.201754, 0.581395, 0.075630, 0.047619, 0.107692, nan, nan, nan, nan
0.024590, 0.026316, 0.162791, 0.008403, 0.000000, 0.007692, 0.914130, nan, nan, nan
0.016393, 0.026316, 0.139535, 0.000000, 0.000000, 0.007692, 0.896739, 0.059140, nan, nan
0.016393, 0.017544, 0.116279, 0.000000, 0.000000, 0.007692, 0.891304, 0.059140, 0.098592, nan
0.016393, 0.017544, 0.116279, 0.000000, 0.000000, 0.007692, 0.885870, 0.059140, 0.098592, 0.031056
"""

EMBEDDED_INFER_AUC_CSV = """
0.508404, nan, nan, nan, nan, nan, nan, nan, nan, nan
0.484248, 0.530348, nan, nan, nan, nan, nan, nan, nan, nan
0.486145, 0.468685, 0.492018, nan, nan, nan, nan, nan, nan, nan
0.478149, 0.452437, 0.491144, 0.548022, nan, nan, nan, nan, nan, nan
0.478149, 0.452437, 0.499340, 0.548022, 0.434211, nan, nan, nan, nan, nan
0.465087, 0.451564, 0.493277, 0.518542, 0.407895, 0.585271, nan, nan, nan, nan
0.480627, 0.590434, 0.524748, 0.537515, 0.473684, 0.497348, 0.350500, nan, nan, nan
0.491326, 0.587130, 0.522272, 0.538602, 0.473684, 0.496091, 0.372225, 0.411558, nan, nan
0.491956, 0.587458, 0.519194, 0.554960, 0.473684, 0.496361, 0.369552, 0.416551, 0.429882, nan
0.491893, 0.581505, 0.517876, 0.554279, 0.473684, 0.497190, 0.368318, 0.416551, 0.431071, 0.388098
"""

EMBEDDED_ORACLE_AUC_CSV = """
0.508404, nan, nan, nan, nan, nan, nan, nan, nan, nan
0.508404, 0.603131, nan, nan, nan, nan, nan, nan, nan, nan
0.508404, 0.603131, 0.515332, nan, nan, nan, nan, nan, nan, nan
0.508404, 0.603131, 0.515332, 0.684092, nan, nan, nan, nan, nan, nan
0.508404, 0.603131, 0.515332, 0.684092, 0.684211, nan, nan, nan, nan, nan
0.508404, 0.603131, 0.515332, 0.684092, 0.684211, 0.605234, nan, nan, nan, nan
0.508404, 0.603131, 0.515332, 0.684092, 0.684211, 0.605234, 0.380243, nan, nan, nan
0.508404, 0.603131, 0.515332, 0.684092, 0.684211, 0.605234, 0.380243, 0.522766, nan, nan
0.508404, 0.603131, 0.515332, 0.684092, 0.684211, 0.605234, 0.380243, 0.522766, 0.838886, nan
0.508404, 0.603131, 0.515332, 0.684092, 0.684211, 0.605234, 0.380243, 0.522766, 0.838886, 0.614736
"""

EMBEDDED_FINAL_CONFUSION_CSV = """
0.016393, 0.008197, 0.065574, 0.000000, 0.000000, 0.008197, 0.827869, 0.049180, 0.016393, 0.008197
0.000000, 0.017544, 0.070175, 0.008772, 0.000000, 0.000000, 0.850877, 0.017544, 0.017544, 0.017544
0.000000, 0.011628, 0.116279, 0.005814, 0.000000, 0.011628, 0.726744, 0.052326, 0.058140, 0.017442
0.008403, 0.067227, 0.075630, 0.000000, 0.000000, 0.008403, 0.663866, 0.050420, 0.100840, 0.025210
0.000000, 0.000000, 0.047619, 0.000000, 0.000000, 0.047619, 0.857143, 0.047619, 0.000000, 0.000000
0.007692, 0.038462, 0.076923, 0.000000, 0.000000, 0.007692, 0.823077, 0.015385, 0.015385, 0.015385
0.001087, 0.011957, 0.051087, 0.001087, 0.000000, 0.007609, 0.885870, 0.026087, 0.009783, 0.005435
0.000000, 0.010753, 0.016129, 0.005376, 0.000000, 0.000000, 0.881720, 0.059140, 0.026882, 0.000000
0.000000, 0.037559, 0.070423, 0.014085, 0.000000, 0.009390, 0.718310, 0.032864, 0.098592, 0.018779
0.000000, 0.012422, 0.093168, 0.006211, 0.000000, 0.012422, 0.745342, 0.031056, 0.068323, 0.031056
"""

PAIR_LABELS = ("ISC_", "LVH")
PAIR_SUMMARY_TEXT = """
sample_id,ecg_id,oracle_task_id,true_label,condition,is_pair_non_easy,was_corrected_to_top1,margin_gain,top1_pred_noprompt,top1_pred_prompt,used_in_plot,proj_x,proj_y
162,162,9,ISC_,noprompt,1,0,-0.14715340733528137,LVH,LVH,1,0.2678664028644562,-0.054050788283348083
162,162,9,ISC_,prompt,1,0,-0.14715340733528137,LVH,LVH,1,0.08682997524738312,-0.19760681688785553
271,271,9,ISC_,noprompt,1,0,-0.055705249309539795,LVH,LVH,1,-0.09699732065200806,0.023979514837265015
271,271,9,ISC_,prompt,1,0,-0.055705249309539795,LVH,LVH,1,-0.14105947315692902,-0.06056339666247368
452,452,9,ISC_,noprompt,1,0,-0.21959400177001953,LVH,LVH,1,0.502670168876648,0.3090794086456299
452,452,9,ISC_,prompt,1,0,-0.21959400177001953,LVH,LVH,1,0.3502529263496399,0.1599009931087494
516,516,9,ISC_,noprompt,1,0,-0.04931129515171051,LVH,LVH,1,-0.30072590708732605,-0.1349230408668518
516,516,9,ISC_,prompt,1,0,-0.04931129515171051,LVH,LVH,1,-0.3231259286403656,-0.20594792068004608
534,534,9,ISC_,noprompt,1,0,-0.13794124126434326,LVH,LVH,1,0.32665926218032837,0.038868315517902374
534,534,9,ISC_,prompt,1,0,-0.13794124126434326,LVH,LVH,1,0.17360010743141174,-0.1171111911535263
1013,1013,9,ISC_,noprompt,1,0,-0.10743877291679382,LVH,LVH,1,0.14759129285812378,-0.00952231790870428
1013,1013,9,ISC_,prompt,1,0,-0.10743877291679382,LVH,LVH,1,0.005267970729619265,-0.12532474100589752
1219,1219,9,LVH,noprompt,0,,0.03263425827026367,LVH,LVH,1,-0.02294236794114113,-0.028781941160559654
1219,1219,9,LVH,prompt,0,,0.03263425827026367,LVH,LVH,1,-0.05959932506084442,-0.14073263108730316
1307,1307,9,LVH,noprompt,0,,0.12188002467155457,LVH,LVH,1,0.061607323586940765,0.14080078899860382
1307,1307,9,LVH,prompt,0,,0.12188002467155457,LVH,LVH,1,-0.05876383185386658,-0.038778871297836304
1320,1320,9,ISC_,noprompt,1,0,-0.0020210333168506622,LVH,LVH,1,-0.5044217705726624,-0.30719059705734253
1320,1320,9,ISC_,prompt,1,0,-0.0020210333168506622,LVH,LVH,1,-0.47736138105392456,-0.2914179861545563
1386,1386,9,LVH,noprompt,0,,0.017759844660758972,LVH,LVH,1,-0.37842410802841187,-0.19502893090248108
1386,1386,9,LVH,prompt,0,,0.017759844660758972,LVH,LVH,1,-0.37838980555534363,-0.23866939544677734
1456,1456,9,ISC_,noprompt,1,0,-0.003187030553817749,LVH,LVH,1,-0.3481767177581787,-0.24356280267238617
1456,1456,9,ISC_,prompt,1,0,-0.003187030553817749,LVH,LVH,1,-0.32026535272598267,-0.2348850965499878
1480,1480,9,LVH,noprompt,0,,0.01716706156730652,LVH,LVH,1,-0.10799790918827057,-0.16827167570590973
1480,1480,9,LVH,prompt,0,,0.01716706156730652,LVH,LVH,1,-0.13421446084976196,-0.2335631549358368
1522,1522,9,LVH,noprompt,0,,0.13331454992294312,LVH,LVH,1,0.15992721915245056,0.12055694311857224
1522,1522,9,LVH,prompt,0,,0.13331454992294312,LVH,LVH,1,0.014965499751269817,-0.04729701578617096
1534,1534,9,LVH,noprompt,0,,-0.006585277616977692,LVH,LVH,1,-0.44173845648765564,-0.3136237859725952
1534,1534,9,LVH,prompt,0,,-0.006585277616977692,LVH,LVH,1,-0.4078345000743866,-0.314796507358551
1961,1961,9,LVH,noprompt,0,,0.013015344738960266,LVH,LVH,1,-0.32449448108673096,-0.22188076376914978
1961,1961,9,LVH,prompt,0,,0.013015344738960266,LVH,LVH,1,-0.31900089979171753,-0.26538947224617004
2064,2064,9,ISC_,noprompt,1,0,0.004881270229816437,LVH,LVH,1,-0.4108034372329712,-0.3480914831161499
2064,2064,9,ISC_,prompt,1,0,0.004881270229816437,LVH,LVH,1,-0.37713462114334106,-0.3509710729122162
2103,2103,9,ISC_,noprompt,1,0,-0.017562061548233032,LVH,LVH,1,-0.25134897232055664,-0.04951866716146469
2103,2103,9,ISC_,prompt,1,0,-0.017562061548233032,LVH,LVH,1,-0.25913506746292114,-0.12306685745716095
2104,2104,9,ISC_,noprompt,1,0,-0.0621299147605896,LVH,LVH,1,-0.13119909167289734,-0.02677898295223713
2104,2104,9,ISC_,prompt,1,0,-0.0621299147605896,LVH,LVH,1,-0.18172454833984375,-0.12233129888772964
2119,2119,9,LVH,noprompt,0,,0.011401087045669556,LVH,LVH,1,-0.4554009735584259,-0.17714904248714447
2119,2119,9,LVH,prompt,0,,0.011401087045669556,LVH,LVH,1,-0.4331231415271759,-0.19064977765083313
2213,2213,9,LVH,noprompt,0,,0.01512540876865387,LVH,LVH,1,-0.40459758043289185,-0.05722963064908981
2213,2213,9,LVH,prompt,0,,0.01512540876865387,LVH,LVH,1,-0.3927733898162842,-0.11112960427999496
2317,2317,9,ISC_,noprompt,1,0,-0.09018546342849731,LVH,LVH,1,-0.09610415995121002,-0.03063231147825718
2317,2317,9,ISC_,prompt,1,0,-0.09018546342849731,LVH,LVH,1,-0.16221629083156586,-0.1391828954219818
2322,2322,9,ISC_,noprompt,1,0,-0.012593686580657959,LVH,LVH,1,-0.22617192566394806,-0.23322610557079315
2322,2322,9,ISC_,prompt,1,0,-0.012593686580657959,LVH,LVH,1,-0.23413872718811035,-0.27355507016181946
2473,2473,9,LVH,noprompt,0,,0.14263224601745605,LVH,LVH,1,0.10538504272699356,0.20962783694267273
2473,2473,9,LVH,prompt,0,,0.14263224601745605,LVH,LVH,1,-0.03295612335205078,0.01631954126060009
2565,2565,9,ISC_,noprompt,1,0,-0.10247069597244263,LVH,LVH,1,0.019135018810629845,-0.03846663981676102
2565,2565,9,ISC_,prompt,1,0,-0.10247069597244263,LVH,LVH,1,-0.07382635772228241,-0.18087376654148102
2693,2693,9,ISC_,noprompt,1,0,-0.009954385459423065,LVH,LVH,1,-0.4516024589538574,-0.2624627351760864
2693,2693,9,ISC_,prompt,1,0,-0.009954385459423065,LVH,LVH,1,-0.4226225018501282,-0.2710379958152771
2802,2802,9,ISC_,noprompt,1,0,-0.010875217616558075,LVH,LVH,1,-0.48645463585853577,-0.27954500913619995
2802,2802,9,ISC_,prompt,1,0,-0.010875217616558075,LVH,LVH,1,-0.4646258056163788,-0.2806525230407715
3092,3092,9,LVH,noprompt,0,,0.15096864104270935,LVH,LVH,1,0.06874994933605194,0.02473512291908264
3092,3092,9,LVH,prompt,0,,0.15096864104270935,LVH,LVH,1,-0.06716921180486679,-0.1179138571023941
3281,3281,9,ISC_,noprompt,1,0,-0.21728968620300293,LVH,LVH,1,0.32864972949028015,0.22999131679534912
3281,3281,9,ISC_,prompt,1,0,-0.21728968620300293,LVH,LVH,1,0.11724038422107697,0.02868923917412758
3371,3371,9,LVH,noprompt,0,,0.23609626293182373,LVH,LVH,1,0.38442790508270264,0.22372296452522278
3371,3371,9,LVH,prompt,0,,0.23609626293182373,LVH,LVH,1,0.18553155660629272,0.0016457820311188698
3454,3454,9,ISC_,noprompt,1,0,-0.13663321733474731,LVH,LVH,1,0.1825263500213623,0.15323704481124878
3454,3454,9,ISC_,prompt,1,0,-0.13663321733474731,LVH,LVH,1,0.06876455247402191,-0.0030840104445815086
3603,3603,9,LVH,noprompt,0,,0.09059330821037292,LVH,LVH,1,-0.14563536643981934,0.08401012420654297
3603,3603,9,LVH,prompt,0,,0.09059330821037292,LVH,LVH,1,-0.22031214833259583,-0.03596733510494232
3606,3606,9,LVH,noprompt,0,,0.052299484610557556,LVH,LVH,1,-0.20145131647586823,-0.2424408346414566
3606,3606,9,LVH,prompt,0,,0.052299484610557556,LVH,LVH,1,-0.24617543816566467,-0.2923429012298584
3660,3660,9,LVH,noprompt,0,,0.011157240718603134,LVH,LVH,1,-0.4817134737968445,-0.29791826009750366
3660,3660,9,LVH,prompt,0,,0.011157240718603134,LVH,LVH,1,-0.4681415557861328,-0.3093140423297882
3785,3785,9,LVH,noprompt,0,,0.050652116537094116,LVH,LVH,1,-0.2073412537574768,-0.050299808382987976
3785,3785,9,LVH,prompt,0,,0.050652116537094116,LVH,LVH,1,-0.25035375356674194,-0.14646375179290771
3827,3827,9,ISC_,noprompt,1,0,0.0057966262102127075,LVH,LVH,1,-0.4158770740032196,-0.07678204774856567
3827,3827,9,ISC_,prompt,1,0,0.0057966262102127075,LVH,LVH,1,-0.3845561444759369,-0.09023333340883255
3867,3867,9,ISC_,noprompt,1,0,-0.13266438245773315,LVH,LVH,1,0.21597102284431458,0.11853724718093872
3867,3867,9,ISC_,prompt,1,0,-0.13266438245773315,LVH,LVH,1,0.08129625767469406,-0.03391563892364502
3869,3869,9,ISC_,noprompt,1,0,-0.16712167859077454,LVH,LVH,1,0.27997887134552,0.13269135355949402
3869,3869,9,ISC_,prompt,1,0,-0.16712167859077454,LVH,LVH,1,0.1065467894077301,-0.07528726011514664
3895,3895,9,ISC_,noprompt,1,0,-0.18487882614135742,LVH,LVH,1,0.3374823331832886,-0.03318343311548233
3895,3895,9,ISC_,prompt,1,0,-0.18487882614135742,LVH,LVH,1,0.127924382686615,-0.1640450358390808
3910,3910,9,ISC_,noprompt,1,0,-0.03865019977092743,LVH,LVH,1,-0.3703320026397705,-0.1531478315591812
3910,3910,9,ISC_,prompt,1,0,-0.03865019977092743,LVH,LVH,1,-0.3820018172264099,-0.21911799907684326
4278,4278,9,LVH,noprompt,0,,0.025993555784225464,LVH,LVH,1,-0.35013097524642944,-0.10785801708698273
4278,4278,9,LVH,prompt,0,,0.025993555784225464,LVH,LVH,1,-0.3452373743057251,-0.15486910939216614
4335,4335,9,ISC_,noprompt,1,0,-0.1992059350013733,LVH,LVH,1,0.44551414251327515,0.19348439574241638
4335,4335,9,ISC_,prompt,1,0,-0.1992059350013733,LVH,LVH,1,0.2572978138923645,-0.010358328931033611
4410,4410,9,ISC_,noprompt,1,0,0.02501162886619568,LVH,LVH,1,-0.35555022954940796,-0.19726590812206268
4410,4410,9,ISC_,prompt,1,0,0.02501162886619568,LVH,LVH,1,-0.3089620769023895,-0.190809428691864
4458,4458,9,LVH,noprompt,0,,0.19924703240394592,LVH,LVH,1,0.2867167592048645,0.27134981751441956
4458,4458,9,LVH,prompt,0,,0.19924703240394592,LVH,LVH,1,0.11204464733600616,0.08481733500957489
4547,4547,9,LVH,noprompt,0,,0.02033981680870056,LVH,LVH,1,-0.31104135513305664,-0.2103646695613861
4547,4547,9,LVH,prompt,0,,0.02033981680870056,LVH,LVH,1,-0.32386428117752075,-0.24745133519172668
4614,4614,9,ISC_,noprompt,1,0,-0.06929504871368408,LVH,LVH,1,-0.11270034313201904,-0.2285209447145462
4614,4614,9,ISC_,prompt,1,0,-0.06929504871368408,LVH,LVH,1,-0.20353910326957703,-0.2781541347503662
4749,4749,9,ISC_,noprompt,1,0,-0.005395576357841492,LVH,LVH,1,-0.207876518368721,-0.23968328535556793
4749,4749,9,ISC_,prompt,1,0,-0.005395576357841492,LVH,LVH,1,-0.2141600251197815,-0.27594685554504395
5087,5087,9,ISC_,noprompt,1,0,-0.13783326745033264,LVH,LVH,1,0.09972654283046722,0.14634597301483154
5087,5087,9,ISC_,prompt,1,0,-0.13783326745033264,LVH,LVH,1,-0.03387784957885742,-0.016162768006324768
5810,5810,9,ISC_,noprompt,1,0,-0.10915321111679077,LVH,LVH,1,0.1882968246936798,-0.029047194868326187
5810,5810,9,ISC_,prompt,1,0,-0.10915321111679077,LVH,LVH,1,0.06645885109901428,-0.16904789209365845
5911,5911,9,LVH,noprompt,0,,0.2001560628414154,LVH,LVH,1,0.2425171285867691,0.36727195978164673
5911,5911,9,LVH,prompt,0,,0.2001560628414154,LVH,LVH,1,0.09248100221157074,0.18413636088371277
6098,6098,9,ISC_,noprompt,1,0,-0.05498109757900238,LVH,LVH,1,-0.21940438449382782,0.028213929384946823
6098,6098,9,ISC_,prompt,1,0,-0.05498109757900238,LVH,LVH,1,-0.2574828863143921,-0.08988262712955475
6141,6141,9,LVH,noprompt,0,,0.1864992082118988,LVH,LVH,1,0.16529637575149536,0.19444027543067932
6141,6141,9,LVH,prompt,0,,0.1864992082118988,LVH,LVH,1,-0.016613636165857315,0.023744400590658188
6180,6180,9,LVH,noprompt,0,,0.06576724350452423,LVH,LVH,1,-0.27627032995224,0.06969515979290009
6180,6180,9,LVH,prompt,0,,0.06576724350452423,LVH,LVH,1,-0.3127981424331665,-0.040972936898469925
6229,6229,9,ISC_,noprompt,1,0,-0.01575601100921631,LVH,LVH,1,-0.27271968126296997,-0.15946510434150696
6229,6229,9,ISC_,prompt,1,0,-0.01575601100921631,LVH,LVH,1,-0.2622452974319458,-0.19151587784290314
6337,6337,9,LVH,noprompt,0,,0.1277630627155304,LVH,LVH,1,0.10582906007766724,0.05873915180563927
6337,6337,9,LVH,prompt,0,,0.1277630627155304,LVH,LVH,1,-0.007125713862478733,-0.05423210188746452
6353,6353,9,ISC_,noprompt,1,0,-0.020837530493736267,LVH,LVH,1,-0.14946328103542328,-0.31198301911354065
6353,6353,9,ISC_,prompt,1,0,-0.020837530493736267,LVH,LVH,1,-0.1895619034767151,-0.3546215295791626
6427,6427,9,LVH,noprompt,0,,0.09991598129272461,LVH,LVH,1,0.10201632976531982,0.11307346820831299
6427,6427,9,LVH,prompt,0,,0.09991598129272461,LVH,LVH,1,0.006165702361613512,-0.039332740008831024
6625,6625,9,LVH,noprompt,0,,0.04368981719017029,LVH,LVH,1,-0.11837182939052582,-0.012672770768404007
6625,6625,9,LVH,prompt,0,,0.04368981719017029,LVH,LVH,1,-0.159315824508667,-0.16017434000968933
6666,6666,9,ISC_,noprompt,1,0,-0.05659842491149902,LVH,LVH,1,0.028030814602971077,-0.059671107679605484
6666,6666,9,ISC_,prompt,1,0,-0.05659842491149902,LVH,LVH,1,-0.03761547803878784,-0.17986515164375305
6788,6788,9,ISC_,noprompt,1,0,0.0027432218194007874,LVH,LVH,1,-0.4332585036754608,-0.2784726023674011
6788,6788,9,ISC_,prompt,1,0,0.0027432218194007874,LVH,LVH,1,-0.40313640236854553,-0.2770429849624634
6925,6925,9,LVH,noprompt,0,,0.15955084562301636,LVH,LVH,1,0.18746095895767212,0.19057299196720123
6925,6925,9,LVH,prompt,0,,0.15955084562301636,LVH,LVH,1,0.019199015572667122,0.007030412554740906
6992,6992,9,ISC_,noprompt,1,0,-0.22422701120376587,LVH,LVH,1,0.29720544815063477,0.17409223318099976
6992,6992,9,ISC_,prompt,1,0,-0.22422701120376587,LVH,LVH,1,0.07079324126243591,-0.04920671135187149
7354,7354,9,LVH,noprompt,0,,0.13641518354415894,LVH,LVH,1,0.17935945093631744,0.030905479565262794
7354,7354,9,LVH,prompt,0,,0.13641518354415894,LVH,LVH,1,0.003514255862683058,-0.1689949482679367
7529,7529,9,ISC_,noprompt,1,0,-0.1622878909111023,LVH,LVH,1,0.2677254378795624,0.23529884219169617
7529,7529,9,ISC_,prompt,1,0,-0.1622878909111023,LVH,LVH,1,0.12455528974533081,0.10624676942825317
7670,7670,9,LVH,noprompt,0,,0.21830469369888306,LVH,LVH,1,0.40634477138519287,0.2766052484512329
7670,7670,9,LVH,prompt,0,,0.21830469369888306,LVH,LVH,1,0.21518221497535706,0.055292755365371704
7684,7684,9,LVH,noprompt,0,,0.006277985870838165,LVH,LVH,1,-0.41882801055908203,-0.19795681536197662
7684,7684,9,LVH,prompt,0,,0.006277985870838165,LVH,LVH,1,-0.39670270681381226,-0.19716574251651764
7812,7812,9,LVH,noprompt,0,,0.11479097604751587,LVH,LVH,1,0.06541913002729416,0.15220072865486145
7812,7812,9,LVH,prompt,0,,0.11479097604751587,LVH,LVH,1,-0.06974669545888901,-0.009982293471693993
7822,7822,9,ISC_,noprompt,1,0,-0.11802911758422852,LVH,LVH,1,0.1738806515932083,-0.02958848513662815
7822,7822,9,ISC_,prompt,1,0,-0.11802911758422852,LVH,LVH,1,0.028989821672439575,-0.17147770524024963
7861,7861,9,ISC_,noprompt,1,0,-0.07514679431915283,LVH,LVH,1,-0.10689348727464676,-0.04203968495130539
7861,7861,9,ISC_,prompt,1,0,-0.07514679431915283,LVH,LVH,1,-0.18683256208896637,-0.16115710139274597
7873,7873,9,ISC_,noprompt,1,0,-0.18599575757980347,LVH,LVH,1,0.29721421003341675,0.24451206624507904
7873,7873,9,ISC_,prompt,1,0,-0.18599575757980347,LVH,LVH,1,0.12975750863552094,0.08535385131835938
7916,7916,9,LVH,noprompt,0,,0.1493251919746399,LVH,LVH,1,0.20031511783599854,0.18859553337097168
7916,7916,9,LVH,prompt,0,,0.1493251919746399,LVH,LVH,1,0.056836970150470734,0.0023787934333086014
7961,7961,9,ISC_,noprompt,1,0,-0.10785329341888428,LVH,LVH,1,-0.02163260243833065,0.05524248629808426
7961,7961,9,ISC_,prompt,1,0,-0.10785329341888428,LVH,LVH,1,-0.13835611939430237,-0.08546677231788635
8083,8083,9,LVH,noprompt,0,,0.048528045415878296,LVH,LVH,1,-0.2701365351676941,-0.07829054445028305
8083,8083,9,LVH,prompt,0,,0.048528045415878296,LVH,LVH,1,-0.31330808997154236,-0.18686528503894806
8121,8121,9,LVH,noprompt,0,,0.027330592274665833,LVH,LVH,1,-0.23221364617347717,-0.06289488822221756
8121,8121,9,LVH,prompt,0,,0.027330592274665833,LVH,LVH,1,-0.2545589804649353,-0.13904765248298645
8209,8209,9,ISC_,noprompt,1,0,-0.0879557728767395,LVH,LVH,1,0.028522226959466934,-0.011993185617029667
8209,8209,9,ISC_,prompt,1,0,-0.0879557728767395,LVH,LVH,1,-0.07205910980701447,-0.13675257563591003
8284,8284,9,LVH,noprompt,0,,0.03840731084346771,LVH,LVH,1,-0.16623355448246002,-0.21531665325164795
8284,8284,9,LVH,prompt,0,,0.03840731084346771,LVH,LVH,1,-0.207923024892807,-0.2753314971923828
8406,8406,9,ISC_,noprompt,1,0,-0.09755593538284302,LVH,LVH,1,0.14234662055969238,-0.11886858195066452
8406,8406,9,ISC_,prompt,1,0,-0.09755593538284302,LVH,LVH,1,-0.004153192974627018,-0.24082568287849426
8501,8501,9,ISC_,noprompt,1,0,-0.00623534619808197,LVH,LVH,1,-0.37307363748550415,-0.2593005895614624
8501,8501,9,ISC_,prompt,1,0,-0.00623534619808197,LVH,LVH,1,-0.35986536741256714,-0.2841683626174927
8524,8524,9,LVH,noprompt,0,,0.015359260141849518,LVH,LVH,1,-0.49769777059555054,-0.35986486077308655
8524,8524,9,LVH,prompt,0,,0.015359260141849518,LVH,LVH,1,-0.48809611797332764,-0.3632936477661133
8772,8772,9,LVH,noprompt,0,,0.07318189740180969,LVH,LVH,1,-0.1274436116218567,0.10759279876947403
8772,8772,9,LVH,prompt,0,,0.07318189740180969,LVH,LVH,1,-0.17774765193462372,-0.005969897843897343
8777,8777,9,LVH,noprompt,0,,0.0001827329397201538,LVH,LVH,1,-0.26576951146125793,-0.1443423330783844
8777,8777,9,LVH,prompt,0,,0.0001827329397201538,LVH,LVH,1,-0.2656165659427643,-0.18843185901641846
8873,8873,9,LVH,noprompt,0,,-0.0032391995191574097,LVH,LVH,1,-0.36625146865844727,-0.10818852484226227
8873,8873,9,LVH,prompt,0,,-0.0032391995191574097,LVH,LVH,1,-0.32255077362060547,-0.12690800428390503
9024,9024,9,LVH,noprompt,0,,0.03287401795387268,LVH,LVH,1,-0.2923722267150879,-0.06297290325164795
9024,9024,9,LVH,prompt,0,,0.03287401795387268,LVH,LVH,1,-0.3012656569480896,-0.14040511846542358
9095,9095,9,ISC_,noprompt,1,0,-0.17772114276885986,LVH,LVH,1,0.19152408838272095,0.17261585593223572
9095,9095,9,ISC_,prompt,1,0,-0.17772114276885986,LVH,LVH,1,0.016672445461153984,-0.013794691301882267
9180,9180,9,ISC_,noprompt,1,0,-0.19890132546424866,LVH,LVH,1,0.2612219750881195,0.18897107243537903
9180,9180,9,ISC_,prompt,1,0,-0.19890132546424866,LVH,LVH,1,0.08292190730571747,-0.013834704644978046
9299,9299,9,LVH,noprompt,0,,0.06531265377998352,LVH,LVH,1,-0.05812234431505203,-0.03193708136677742
9299,9299,9,LVH,prompt,0,,0.06531265377998352,LVH,LVH,1,-0.14657637476921082,-0.15157656371593475
9613,9613,9,ISC_,noprompt,1,0,-0.20639073848724365,LVH,LVH,1,0.43605244159698486,0.2215794324874878
9613,9613,9,ISC_,prompt,1,0,-0.20639073848724365,LVH,LVH,1,0.2449982762336731,0.04740137606859207
9756,9756,9,ISC_,noprompt,1,0,-0.1716676950454712,LVH,LVH,1,0.5549843311309814,0.24989722669124603
9756,9756,9,ISC_,prompt,1,0,-0.1716676950454712,LVH,LVH,1,0.47515732049942017,0.1407214105129242
9867,9867,9,ISC_,noprompt,1,0,-0.06370341777801514,LVH,LVH,1,-0.10065044462680817,0.09620144963264465
9867,9867,9,ISC_,prompt,1,0,-0.06370341777801514,LVH,LVH,1,-0.15294654667377472,-0.003924684599041939
10054,10054,9,ISC_,noprompt,1,0,-0.04348906874656677,LVH,LVH,1,-0.2505515515804291,-0.019232438877224922
10054,10054,9,ISC_,prompt,1,0,-0.04348906874656677,LVH,LVH,1,-0.2746933400630951,-0.08652221411466599
10061,10061,9,ISC_,noprompt,1,0,-0.1515590250492096,LVH,LVH,1,0.1849989891052246,0.1593683362007141
10061,10061,9,ISC_,prompt,1,0,-0.1515590250492096,LVH,LVH,1,0.017056990414857864,-0.012782351113855839
10115,10115,9,ISC_,noprompt,1,0,-0.10325071215629578,LVH,LVH,1,0.032687440514564514,0.06076251342892647
10115,10115,9,ISC_,prompt,1,0,-0.10325071215629578,LVH,LVH,1,-0.09090493619441986,-0.12560740113258362
10177,10177,9,ISC_,noprompt,1,0,-0.04924103617668152,LVH,LVH,1,-0.13112619519233704,-0.20809626579284668
10177,10177,9,ISC_,prompt,1,0,-0.04924103617668152,LVH,LVH,1,-0.16876928508281708,-0.2598637342453003
10180,10180,9,LVH,noprompt,0,,0.1145181655883789,LVH,LVH,1,0.03311043232679367,0.12016096711158752
10180,10180,9,LVH,prompt,0,,0.1145181655883789,LVH,LVH,1,-0.09970492124557495,-0.03080807253718376
10205,10205,9,LVH,noprompt,0,,0.15622037649154663,LVH,LVH,1,0.18597877025604248,0.00987326167523861
10205,10205,9,LVH,prompt,0,,0.15622037649154663,LVH,LVH,1,-0.002274765633046627,-0.19395729899406433
10388,10388,9,LVH,noprompt,0,,0.0022339709103107452,LVH,LVH,1,-0.4768618941307068,-0.267767995595932
10388,10388,9,LVH,prompt,0,,0.0022339709103107452,LVH,LVH,1,-0.4473022520542145,-0.2689933180809021
10563,10563,9,ISC_,noprompt,1,0,-0.10689389705657959,LVH,LVH,1,0.0334683433175087,-0.13676747679710388
10563,10563,9,ISC_,prompt,1,0,-0.10689389705657959,LVH,LVH,1,-0.11055544763803482,-0.22191524505615234
10594,10594,9,ISC_,noprompt,1,0,-0.24623507261276245,LVH,LVH,1,0.39144521951675415,0.3122342526912689
10594,10594,9,ISC_,prompt,1,0,-0.24623507261276245,LVH,LVH,1,0.1860230565071106,0.08469066023826599
10640,10640,9,ISC_,noprompt,1,0,0.003278285264968872,LVH,LVH,1,-0.492217481136322,-0.2982140779495239
10640,10640,9,ISC_,prompt,1,0,0.003278285264968872,LVH,LVH,1,-0.45949798822402954,-0.29193922877311707
11132,11132,9,ISC_,noprompt,1,0,-0.16319727897644043,LVH,LVH,1,0.21749019622802734,0.3814367651939392
11132,11132,9,ISC_,prompt,1,0,-0.16319727897644043,LVH,LVH,1,0.0955539122223854,0.21466729044914246
11139,11139,9,ISC_,noprompt,1,0,-0.015267938375473022,LVH,LVH,1,-0.22241179645061493,-0.05554230883717537
11139,11139,9,ISC_,prompt,1,0,-0.015267938375473022,LVH,LVH,1,-0.21876409649848938,-0.13217014074325562
11755,11755,9,ISC_,noprompt,1,0,-0.1910730004310608,LVH,LVH,1,0.4237329065799713,0.2243710607290268
11755,11755,9,ISC_,prompt,1,0,-0.1910730004310608,LVH,LVH,1,0.2535684406757355,0.03905365988612175
11901,11901,9,ISC_,noprompt,1,0,-0.14910820126533508,LVH,LVH,1,0.19979757070541382,0.05118348076939583
11901,11901,9,ISC_,prompt,1,0,-0.14910820126533508,LVH,LVH,1,0.032819509506225586,-0.13041172921657562
12031,12031,9,LVH,noprompt,0,,0.18838980793952942,LVH,LVH,1,0.26361462473869324,0.3029292821884155
12031,12031,9,LVH,prompt,0,,0.18838980793952942,LVH,LVH,1,0.08141690492630005,0.10457753390073776
12122,12122,9,LVH,noprompt,0,,0.04240898787975311,LVH,LVH,1,-0.152535080909729,-0.2513582408428192
12122,12122,9,LVH,prompt,0,,0.04240898787975311,LVH,LVH,1,-0.22336851060390472,-0.30962255597114563
12252,12252,9,ISC_,noprompt,1,0,-0.10768473148345947,LVH,LVH,1,0.2815779447555542,-0.12047834694385529
12252,12252,9,ISC_,prompt,1,0,-0.10768473148345947,LVH,LVH,1,0.13205191493034363,-0.22874274849891663
12301,12301,9,LVH,noprompt,0,,0.0063127875328063965,LVH,LVH,1,-0.2877381145954132,-0.26829564571380615
12301,12301,9,LVH,prompt,0,,0.0063127875328063965,LVH,LVH,1,-0.27695637941360474,-0.29094088077545166
12338,12338,9,LVH,noprompt,0,,0.13479843735694885,LVH,LVH,1,0.04780863597989082,0.18741482496261597
12338,12338,9,LVH,prompt,0,,0.13479843735694885,LVH,LVH,1,-0.08068552613258362,0.028220411390066147
12585,12585,9,LVH,noprompt,0,,0.07151314616203308,LVH,LVH,1,-0.0712493360042572,-0.06369186192750931
12585,12585,9,LVH,prompt,0,,0.07151314616203308,LVH,LVH,1,-0.11198274791240692,-0.17173853516578674
12646,12646,9,ISC_,noprompt,1,0,-0.06011590361595154,LVH,LVH,1,-0.04028400033712387,0.0860074833035469
12646,12646,9,ISC_,prompt,1,0,-0.06011590361595154,LVH,LVH,1,-0.09504222869873047,0.01843949966132641
12649,12649,9,ISC_,noprompt,1,0,-0.09189143776893616,LVH,LVH,1,-0.027055663987994194,0.04820439964532852
12649,12649,9,ISC_,prompt,1,0,-0.09189143776893616,LVH,LVH,1,-0.12691521644592285,-0.08075354993343353
12719,12719,9,LVH,noprompt,0,,0.02436034381389618,LVH,LVH,1,-0.24251843988895416,-0.17300599813461304
12719,12719,9,LVH,prompt,0,,0.02436034381389618,LVH,LVH,1,-0.25656190514564514,-0.23816819489002228
13007,13007,9,ISC_,noprompt,1,0,-0.05023849010467529,LVH,LVH,1,0.05076669156551361,-0.22327831387519836
13007,13007,9,ISC_,prompt,1,0,-0.05023849010467529,LVH,LVH,1,-0.010518079623579979,-0.3106585443019867
13233,13233,9,ISC_,noprompt,1,0,-0.20336699485778809,LVH,LVH,1,0.35437458753585815,0.1521698236465454
13233,13233,9,ISC_,prompt,1,0,-0.20336699485778809,LVH,LVH,1,0.11808712780475616,-0.04321736842393875
13556,13556,9,ISC_,noprompt,1,0,-0.1820330023765564,LVH,LVH,1,0.4263259768486023,0.09705165773630142
13556,13556,9,ISC_,prompt,1,0,-0.1820330023765564,LVH,LVH,1,0.2265286147594452,-0.07295188307762146
13666,13666,9,LVH,noprompt,0,,0.08259361982345581,LVH,LVH,1,0.11087165027856827,0.07204366475343704
13666,13666,9,LVH,prompt,0,,0.08259361982345581,LVH,LVH,1,0.01631329208612442,-0.07292266190052032
13835,13835,9,LVH,noprompt,0,,0.0697392076253891,LVH,LVH,1,-0.18805590271949768,-2.6284251362085342e-05
13835,13835,9,LVH,prompt,0,,0.0697392076253891,LVH,LVH,1,-0.23564302921295166,-0.09136773645877838
13899,13899,9,ISC_,noprompt,1,0,-0.03480665385723114,LVH,LVH,1,-0.27278977632522583,-0.2200794219970703
13899,13899,9,ISC_,prompt,1,0,-0.03480665385723114,LVH,LVH,1,-0.293035089969635,-0.26566916704177856
14004,14004,9,ISC_,noprompt,1,0,-0.13670441508293152,LVH,LVH,1,0.09870349615812302,0.022584296762943268
14004,14004,9,ISC_,prompt,1,0,-0.13670441508293152,LVH,LVH,1,-0.06409257650375366,-0.14328806102275848
14026,14026,9,ISC_,noprompt,1,0,-0.006177797913551331,LVH,LVH,1,-0.3667721748352051,-0.20504041016101837
14026,14026,9,ISC_,prompt,1,0,-0.006177797913551331,LVH,LVH,1,-0.34179171919822693,-0.25288695096969604
14167,14167,9,LVH,noprompt,0,,0.23240536451339722,LVH,LVH,1,0.5283969640731812,0.20867308974266052
14167,14167,9,LVH,prompt,0,,0.23240536451339722,LVH,LVH,1,0.34573277831077576,0.011063278652727604
14201,14201,9,ISC_,noprompt,1,0,-0.2129223346710205,LVH,LVH,1,0.5191229581832886,0.3697362542152405
14201,14201,9,ISC_,prompt,1,0,-0.2129223346710205,LVH,LVH,1,0.38257911801338196,0.21592578291893005
14350,14350,9,ISC_,noprompt,1,0,-0.006886020302772522,LVH,LVH,1,-0.33850908279418945,-0.24944549798965454
14350,14350,9,ISC_,prompt,1,0,-0.006886020302772522,LVH,LVH,1,-0.318747878074646,-0.27193114161491394
14670,14670,9,ISC_,noprompt,1,0,-0.011060178279876709,LVH,LVH,1,-0.3760223984718323,-0.2685486972332001
14670,14670,9,ISC_,prompt,1,0,-0.011060178279876709,LVH,LVH,1,-0.36259403824806213,-0.2867732048034668
14805,14805,9,LVH,noprompt,0,,0.044489145278930664,LVH,LVH,1,-0.22206489741802216,0.004264437593519688
14805,14805,9,LVH,prompt,0,,0.044489145278930664,LVH,LVH,1,-0.23528048396110535,-0.10279357433319092
14869,14869,9,ISC_,noprompt,1,0,-0.13264179229736328,LVH,LVH,1,0.1182151511311531,0.18808749318122864
14869,14869,9,ISC_,prompt,1,0,-0.13264179229736328,LVH,LVH,1,0.009376559406518936,0.06348036229610443
15500,15500,9,ISC_,noprompt,1,0,-0.18058806657791138,LVH,LVH,1,0.36144760251045227,0.11520034819841385
15500,15500,9,ISC_,prompt,1,0,-0.18058806657791138,LVH,LVH,1,0.18533751368522644,-0.05529604107141495
15787,15787,9,ISC_,noprompt,1,0,-0.211184561252594,LVH,LVH,1,0.45706766843795776,0.3214195966720581
15787,15787,9,ISC_,prompt,1,0,-0.211184561252594,LVH,LVH,1,0.33240675926208496,0.15710240602493286
15797,15797,9,ISC_,noprompt,1,0,-0.02091100811958313,LVH,LVH,1,-0.1745508909225464,-0.1194324940443039
15797,15797,9,ISC_,prompt,1,0,-0.02091100811958313,LVH,LVH,1,-0.17176473140716553,-0.16816309094429016
15863,15863,9,ISC_,noprompt,1,0,-0.06972172856330872,LVH,LVH,1,-0.03701060637831688,0.00023167487233877182
15863,15863,9,ISC_,prompt,1,0,-0.06972172856330872,LVH,LVH,1,-0.10744190216064453,-0.09912188351154327
15871,15871,9,ISC_,noprompt,1,0,-0.2226448655128479,LVH,LVH,1,0.48922792077064514,0.08017980307340622
15871,15871,9,ISC_,prompt,1,0,-0.2226448655128479,LVH,LVH,1,0.2522725462913513,-0.12474454939365387
16045,16045,9,LVH,noprompt,0,,0.1190500557422638,LVH,LVH,1,-0.025315633043646812,0.2871624231338501
16045,16045,9,LVH,prompt,0,,0.1190500557422638,LVH,LVH,1,-0.1335940957069397,0.14561568200588226
16182,16182,9,LVH,noprompt,0,,0.16607993841171265,LVH,LVH,1,0.4257323741912842,0.16821259260177612
16182,16182,9,LVH,prompt,0,,0.16607993841171265,LVH,LVH,1,0.26368385553359985,-0.010367773473262787
16214,16214,9,LVH,noprompt,0,,0.07777443528175354,LVH,LVH,1,-0.07070264965295792,-0.012477574869990349
16214,16214,9,LVH,prompt,0,,0.07777443528175354,LVH,LVH,1,-0.16284236311912537,-0.130262091755867
16591,16591,9,ISC_,noprompt,1,0,-0.14381572604179382,LVH,LVH,1,0.30436471104621887,0.04665880650281906
16591,16591,9,ISC_,prompt,1,0,-0.14381572604179382,LVH,LVH,1,0.1380508542060852,-0.0951637253165245
16609,16609,9,ISC_,noprompt,1,0,-0.032015085220336914,LVH,LVH,1,-0.226223886013031,-0.2052817940711975
16609,16609,9,ISC_,prompt,1,0,-0.032015085220336914,LVH,LVH,1,-0.2605729401111603,-0.2596454322338104
16876,16876,9,ISC_,noprompt,1,0,-0.197742760181427,LVH,LVH,1,0.4948529899120331,0.23193645477294922
16876,16876,9,ISC_,prompt,1,0,-0.197742760181427,LVH,LVH,1,0.36047977209091187,0.08700131624937057
16944,16944,9,LVH,noprompt,0,,0.03854018449783325,LVH,LVH,1,-0.3382492661476135,-0.08273180574178696
16944,16944,9,LVH,prompt,0,,0.03854018449783325,LVH,LVH,1,-0.34308519959

44977,-0.13646218180656433
17226,17226,9,LVH,noprompt,0,,0.06054055690765381,LVH,LVH,1,-0.16965404152870178,0.023798590525984764
17226,17226,9,LVH,prompt,0,,0.06054055690765381,LVH,LVH,1,-0.21242383122444153,-0.09139446914196014
17286,17286,9,ISC_,noprompt,1,0,-0.1686769723892212,LVH,LVH,1,0.3731457591056824,0.164602592587471
17286,17286,9,ISC_,prompt,1,0,-0.1686769723892212,LVH,LVH,1,0.20130114257335663,0.0014913864433765411
17298,17298,9,LVH,noprompt,0,,0.1707715392112732,LVH,LVH,1,0.3460303843021393,0.22389334440231323
17298,17298,9,LVH,prompt,0,,0.1707715392112732,LVH,LVH,1,0.1880010962486267,0.07346144318580627
17309,17309,9,ISC_,noprompt,1,0,-0.1896490454673767,LVH,LVH,1,0.21844711899757385,0.037247538566589355
17309,17309,9,ISC_,prompt,1,0,-0.1896490454673767,LVH,LVH,1,0.027368560433387756,-0.12267456203699112
17325,17325,9,LVH,noprompt,0,,0.1248779296875,LVH,LVH,1,0.16225267946720123,0.11271890997886658
17325,17325,9,LVH,prompt,0,,0.1248779296875,LVH,LVH,1,0.02310757339000702,-0.07129678875207901
17701,17701,9,LVH,noprompt,0,,0.07083705067634583,LVH,LVH,1,-0.06760884076356888,0.18296410143375397
17701,17701,9,LVH,prompt,0,,0.07083705067634583,LVH,LVH,1,-0.12252061814069748,0.08036750555038452
17866,17866,9,LVH,noprompt,0,,0.09767159819602966,LVH,LVH,1,-0.05677793547511101,-0.24166738986968994
17866,17866,9,LVH,prompt,0,,0.09767159819602966,LVH,LVH,1,-0.15504375100135803,-0.31882333755493164
17868,17868,9,LVH,noprompt,0,,0.11957484483718872,LVH,LVH,1,0.14737237989902496,-0.137262225151062
17868,17868,9,LVH,prompt,0,,0.11957484483718872,LVH,LVH,1,-0.011298829689621925,-0.26314276456832886
18017,18017,9,LVH,noprompt,0,,0.020465627312660217,LVH,LVH,1,-0.3118661642074585,-0.1710021197795868
18017,18017,9,LVH,prompt,0,,0.020465627312660217,LVH,LVH,1,-0.3341914117336273,-0.24008804559707642
18162,18162,9,ISC_,noprompt,1,0,-0.18471890687942505,LVH,LVH,1,0.3839637041091919,-0.04877297580242157
18162,18162,9,ISC_,prompt,1,0,-0.18471890687942505,LVH,LVH,1,0.17615914344787598,-0.20855596661567688
18234,18234,9,LVH,noprompt,0,,0.1070641279220581,LVH,LVH,1,0.05227284878492355,0.10779128968715668
18234,18234,9,LVH,prompt,0,,0.1070641279220581,LVH,LVH,1,-0.06945624947547913,-0.055118754506111145
18296,18296,9,ISC_,noprompt,1,0,-0.06676393747329712,LVH,LVH,1,-0.050246335566043854,0.0004467112012207508
18296,18296,9,ISC_,prompt,1,0,-0.06676393747329712,LVH,LVH,1,-0.12935049831867218,-0.10346107184886932
18644,18644,9,LVH,noprompt,0,,0.008317410945892334,LVH,LVH,1,-0.3843775987625122,-0.18586260080337524
18644,18644,9,LVH,prompt,0,,0.008317410945892334,LVH,LVH,1,-0.36413586139678955,-0.19549183547496796
18676,18676,9,ISC_,noprompt,1,0,-0.06470245122909546,LVH,LVH,1,-0.003054298460483551,-0.2227354347705841
18676,18676,9,ISC_,prompt,1,0,-0.06470245122909546,LVH,LVH,1,-0.09394746273756027,-0.31062281131744385
18712,18712,9,ISC_,noprompt,1,0,-0.2181439995765686,LVH,LVH,1,0.39044320583343506,0.1438772976398468
18712,18712,9,ISC_,prompt,1,0,-0.2181439995765686,LVH,LVH,1,0.1827344298362732,-0.08666647970676422
19526,19526,9,ISC_,noprompt,1,0,-0.1666048765182495,LVH,LVH,1,0.36510762572288513,0.17956723272800446
19526,19526,9,ISC_,prompt,1,0,-0.1666048765182495,LVH,LVH,1,0.21193251013755798,0.04298735409975052
20211,20211,9,LVH,noprompt,0,,0.19823449850082397,LVH,LVH,1,0.19898547232151031,0.15425756573677063
20211,20211,9,LVH,prompt,0,,0.19823449850082397,LVH,LVH,1,0.010558504611253738,-0.06695379316806793
20236,20236,9,ISC_,noprompt,1,0,-0.20385217666625977,LVH,LVH,1,0.4467070996761322,0.3760039806365967
20236,20236,9,ISC_,prompt,1,0,-0.20385217666625977,LVH,LVH,1,0.29138660430908203,0.19806508719921112
20242,20242,9,LVH,noprompt,0,,0.1895110309123993,LVH,LVH,1,0.23286807537078857,0.03456788882613182
20242,20242,9,LVH,prompt,0,,0.1895110309123993,LVH,LVH,1,0.0196638572961092,-0.14073511958122253
20369,20369,9,LVH,noprompt,0,,0.17506450414657593,LVH,LVH,1,0.2063712477684021,0.17521171271800995
20369,20369,9,LVH,prompt,0,,0.17506450414657593,LVH,LVH,1,0.05626995116472244,-0.016779545694589615
21021,21021,9,ISC_,noprompt,1,0,-0.15273258090019226,LVH,LVH,1,0.3056766092777252,-0.15424993634223938
21021,21021,9,ISC_,prompt,1,0,-0.15273258090019226,LVH,LVH,1,0.13791730999946594,-0.2598782777786255
21104,21104,9,ISC_,noprompt,1,0,-0.12258440256118774,LVH,LVH,1,0.32567453384399414,-0.08940017968416214
21104,21104,9,ISC_,prompt,1,0,-0.12258440256118774,LVH,LVH,1,0.17377525568008423,-0.2258286327123642
21173,21173,9,ISC_,noprompt,1,0,-0.2612963318824768,LVH,LVH,1,0.4909355640411377,0.11921227723360062
21173,21173,9,ISC_,prompt,1,0,-0.2612963318824768,LVH,LVH,1,0.2521728277206421,-0.0925387293100357
21555,21555,9,ISC_,noprompt,1,0,-0.212782621383667,LVH,LVH,1,0.45859548449516296,0.10895854979753494
21555,21555,9,ISC_,prompt,1,0,-0.212782621383667,LVH,LVH,1,0.2557072937488556,-0.042026277631521225
"""

BAR_STATS = [
    {"group": "already_correct", "n": 1706, "positive_rate": 0.9314185228604924},
    {"group": "near_miss", "n": 146, "positive_rate": 0.03424657534246575},
    {"group": "hard_error", "n": 306, "positive_rate": 0.3300653594771242},
]

# =========================
# 二、全局样式参数
# 作用：统一控制字体、颜色、字号、柱形纹理等视觉风格。
# 老师如果要改图的外观，优先看这一块。
# =========================

PANEL_LABEL_FONTSIZE = 18.0
AXIS_LABEL_FONTSIZE = 15.0
TICK_LABEL_FONTSIZE = 13.0
LEGEND_FONTSIZE = 12.2
VALUE_LABEL_FONTSIZE = 14.0
PANEL_C_VALUE_FONTSIZE = 16.0
CBAR_PAD_FRACTION = 0.012
CBAR_WIDTH_FRACTION = 0.022
CBAR_HEIGHT_FRACTION = 0.92
CBAR_Y_OFFSET_FRACTION = 0.04
CBAR_DX = 0.0
CBAR_DY = 0.0
CBAR_DW = -0.10
CBAR_DH = 0.0
INSET_TITLE_FONTSIZE = 10.5
INSET_SUBTITLE_FONTSIZE = 9.4
INSET_SUMMARY_FONTSIZE = 8.8

TEXT_COLOR = "#1A1A1A"
GRID_COLOR = "#E6E6E6"
FACE_COLOR = "#FAFAFA"
BAR_BACKGROUND_COLOR = "#FFFFFF"
BAR_EDGE_COLOR = "#333333"
INFERRED_BAR_COLOR = to_rgba("#4DBBD5", alpha=0.32)  # Nature palette
ORACLE_BAR_COLOR = to_rgba("#3C5488", alpha=0.32)  # Nature palette
BAR_GAIN_COLOR = to_rgba("#E64B35", alpha=0.32)  # Nature palette

MARGIN_BG_COLOR = "#F8F8F8"
MARGIN_BAR_COLORS = [
    to_rgba("#3C5488", alpha=0.32),
    to_rgba("#4DBBD5", alpha=0.32),
    to_rgba("#E64B35", alpha=0.32),
]
MARGIN_BAR_HATCHES = ["/", ".", "x"]
MARGIN_HATCH_EDGE_COLOR = "#333333"
MARGIN_GRID_COLOR = "#E5E5E5"
MARGIN_TEXT_COLOR = "#1A1A1A"
MARGIN_GUIDE_COLOR = "#B0B0B0"
MARGIN_SPINE_COLOR = "#333333"
BACKGROUND_COLOR = to_rgba("#D0D0D0", alpha=0.32)
PAIR_COLORS = {
    "A": to_rgba("#3C5488", alpha=0.32),
    "B": to_rgba("#E64B35", alpha=0.32),
}
PAIR_CENTER_COLORS = {"A": "#3C5488", "B": "#E64B35"}
INSET_CONDITION_COLORS = {
    "noprompt": {
        "A": to_rgba("#7EA3C9", alpha=0.45),
        "B": to_rgba("#C76D5E", alpha=0.45),
        "A_center": "#7EA3C9",
        "B_center": "#C76D5E",
    },
    "prompt": {
        "A": to_rgba("#00A087", alpha=0.60),
        "B": to_rgba("#E64B35", alpha=0.60),
        "A_center": "#00A087",
        "B_center": "#E64B35",
    },
}


# =========================
# 三、参数解析与基础配置
# 作用：读取命令行参数，并设置 matplotlib 的全局绘图风格。
# =========================


def parse_args() -> argparse.Namespace:
    # 定义脚本运行时可调整的输出路径、画布尺寸和分辨率。
    parser = argparse.ArgumentParser(
        description="Redraw three prompt-analysis panels into one self-contained figure."
    )
    parser.add_argument(
        "--output-png", default=str(DEFAULT_OUTPUT_PNG), help="Output PNG path."
    )
    parser.add_argument(
        "--output-pdf", default=str(DEFAULT_OUTPUT_PDF), help="Output PDF path."
    )
    parser.add_argument(
        "--fig-width", type=float, default=18, help="Figure width in inches."
    )
    parser.add_argument(
        "--fig-height", type=float, default=4, help="Figure height in inches."
    )
    parser.add_argument("--dpi", type=int, default=600, help="Output DPI.")
    return parser.parse_args()


def configure_matplotlib() -> None:
    # 统一设置全局字体、线宽和导出格式，保证三联图风格一致。
    import matplotlib.pyplot as plt

    plt.rcParams.update(
        {
            "font.family": "Arial",
            "font.sans-serif": ["Arial", "Helvetica", "DejaVu Sans"],
            "mathtext.fontset": "cm",
            # "font.weight": "bold",
            "font.size": 14,
            "axes.labelsize": 14,
            "axes.titlesize": 14,
            # "axes.labelweight": "bold",
            # "axes.titleweight": "bold",
            "xtick.labelsize": 14,
            "ytick.labelsize": 14,
            "xtick.direction": "out",
            "ytick.direction": "out",
            "xtick.major.size": 8,
            "ytick.major.size": 8,
            "xtick.major.width": 1,
            "ytick.major.width": 1,
            "legend.fontsize": 14,
            "axes.linewidth": 1.10,
            "hatch.linewidth": 0.70,
            "pdf.fonttype": 42,
            "ps.fonttype": 42,
            "figure.facecolor": "white",
            "savefig.facecolor": "white",
        }
    )


# =========================
# 四、数据读取与预处理
# 作用：把上面的文本数据转成矩阵/样本列表，供后面的绘图函数直接调用。
# =========================


def load_embedded_matrix(csv_text: str) -> np.ndarray:
    # 将内嵌 CSV 字符串解析为 numpy 矩阵。
    return np.genfromtxt(StringIO(csv_text.strip()), delimiter=",", dtype=np.float32)


def load_confusion_data() -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
    # 一次性返回 panel (a)(b) 需要的四个核心矩阵。
    return (
        load_embedded_matrix(EMBEDDED_ROUTING_ACCURACY_CSV),
        load_embedded_matrix(EMBEDDED_INFER_AUC_CSV),
        load_embedded_matrix(EMBEDDED_ORACLE_AUC_CSV),
        load_embedded_matrix(EMBEDDED_FINAL_CONFUSION_CSV),
    )


def load_pair_rows() -> list[dict[str, object]]:
    # 读取用于 panel (c) 小嵌入图的样本点，只保留 used_in_plot=1 的记录。
    rows: list[dict[str, object]] = []
    reader = csv.DictReader(StringIO(PAIR_SUMMARY_TEXT.strip()))
    for raw in reader:
        if raw["used_in_plot"] != "1":
            continue
        proj_x_raw = raw.get("proj_x")
        proj_y_raw = raw.get("proj_y")
        if proj_x_raw is None or proj_y_raw is None:
            continue
        try:
            proj_x = float(proj_x_raw)
            proj_y = float(proj_y_raw)
        except (TypeError, ValueError):
            continue
        rows.append(
            {
                "true_label": raw["true_label"],
                "condition": raw["condition"].lower(),
                "is_pair_non_easy": raw["is_pair_non_easy"] == "1",
                "proj_x": proj_x,
                "proj_y": proj_y,
            }
        )
    return rows


def build_pair_plot(rows: list[dict[str, object]]) -> dict[str, object]:
    # 按 prompt / no-prompt 分组，并计算两类样本的中心点和显示范围。
    rows_by_condition = {
        "noprompt": [row for row in rows if row["condition"] == "noprompt"],
        "prompt": [row for row in rows if row["condition"] == "prompt"],
    }

    x_all = [float(row["proj_x"]) for row in rows]
    y_all = [float(row["proj_y"]) for row in rows]
    x_min, x_max = min(x_all), max(x_all)
    y_min, y_max = min(y_all), max(y_all)
    x_pad = max((x_max - x_min) * 0.08, 0.035)
    y_pad = max((y_max - y_min) * 0.08, 0.035)

    centers: dict[str, dict[str, tuple[float, float]]] = {}
    for condition, subset in rows_by_condition.items():
        centers[condition] = {}
        for label in PAIR_LABELS:
            class_rows = [row for row in subset if row["true_label"] == label]
            xs = np.array([row["proj_x"] for row in class_rows], dtype=np.float32)
            ys = np.array([row["proj_y"] for row in class_rows], dtype=np.float32)
            centers[condition][label] = (float(xs.mean()), float(ys.mean()))

    return {
        "pair_labels": list(PAIR_LABELS),
        "rows_by_condition": rows_by_condition,
        "centers": centers,
        "xlim": (x_min - x_pad, x_max + x_pad),
        "ylim": (y_min - y_pad, y_max + y_pad),
    }


# =========================
# 五、通用绘图小工具
# 作用：封装面板编号、刻度加粗、热力图文字颜色等重复逻辑。
# =========================


def draw_panel_label(ax, label: str, x: float = -12.0, y: float = -12.0) -> None:
    # 在每个主子图区域左下角添加 (a)(b)(c)，避免受各自 axes 高宽比影响而错位。
    from matplotlib.transforms import offset_copy

    fig = ax.figure
    top_spec = ax.get_subplotspec().get_topmost_subplotspec()
    bbox = top_spec.get_position(fig)
    text_transform = offset_copy(fig.transFigure, fig=fig, x=x, y=y, units="points")

    if label == '(a)':
        pad_x = 0.032
    if label == '(b)':
        pad_x = 0.032
    if label == '(c)':
        pad_x = 0.032

    fig.text(
        bbox.x0 - pad_x,
        bbox.y0 - 0.13,
        label,
        transform=text_transform,
        ha="left",
        va="bottom",
        fontsize=14,
        fontweight="bold",
        color="black",
    )


def set_tick_bold(ax, fontsize: float | None = None) -> None:
    # 统一把坐标轴刻度文字设为粗体。
    for label in ax.get_xticklabels() + ax.get_yticklabels():
        label.set_fontweight("bold")
        if fontsize is not None:
            label.set_fontsize(fontsize)


def heatmap_text_color(mappable, value: float) -> str:
    # 根据底色明暗自动选择黑字或白字，避免热力图数字看不清。
    rgba = mappable.cmap(mappable.norm(value))
    r, g, b = rgba[:3]
    luminance = 0.299 * r + 0.587 * g + 0.114 * b
    return "white" if luminance < 0.50 else "black"


def format_heatmap_value(value: float) -> str:
    # 将 0~1 的比例转成两位整数百分数，例如 0.83 -> "83"。
    return f"{int(np.rint(value * 100)):02d}"


# =========================
# 六、Panel (a): 最终任务混淆矩阵
# 作用：展示最终预测任务与真实任务之间的混淆关系。
# =========================


def draw_confusion_panel(fig, heatmap_spec, cbar_spec) -> None:
    # 画左侧热力图，并重点标出第 7 列（T7）的数值。
    from matplotlib.colors import LinearSegmentedColormap
    from matplotlib.patches import Rectangle

    _, _, _, final_confusion = load_confusion_data()
    num_tasks = final_confusion.shape[0]
    cmap = LinearSegmentedColormap.from_list(
        "water_blue_to_water_red",
        [
            to_rgba("#4DBBD5", alpha=0.9),
            to_rgba("#8FD3E8", alpha=0.32),
            to_rgba("#E89AA0", alpha=0.32),
            to_rgba("#E64B35", alpha=0.9),
        ],
    )

    ax = fig.add_subplot(heatmap_spec)

    ax.set_facecolor(FACE_COLOR)
    # Keep panel shape stable without over-constraining outer layout spacing.
    x_edges = np.arange(num_tasks + 1)
    y_edges = np.arange(num_tasks + 1)
    im = ax.pcolormesh(
        x_edges,
        y_edges,
        final_confusion,
        cmap=cmap,
        vmin=0.0,
        vmax=1.0,
        shading="flat",
        edgecolors="#FFFFFF",
        linewidth=0.6,
    )
    ax.set_ylim(num_tasks, 0)
    ax.set_box_aspect(1)
    cax = fig.add_subplot(cbar_spec)
    apos = ax.get_position()
    cpos = cax.get_position()
    cax.set_position(
        [
            cpos.x0 + cpos.width * CBAR_DX - 0.04,
            apos.y0,
            cpos.width * (1.3 + CBAR_DW),
            apos.height,
        ]
    )
    cbar = fig.colorbar(im, cax=cax)
    cbar.set_ticks(np.linspace(0.0, 1.0, 6))
    cbar.set_ticklabels([f"{v:.1f}" for v in np.linspace(0.0, 1.0, 6)])
    cbar.set_label("Fraction", color=TEXT_COLOR, labelpad=5)
    # cbar.outline.set_linewidth(0.85)
    # cbar.outline.set_edgecolor("#6A6A6A")
    # cbar.ax.tick_params(width=0.85, length=3, pad=1.0, colors=TEXT_COLOR)
    # for label in cbar.ax.get_yticklabels():
    #     label.set_fontweight("bold")

    ax.set_xticks(np.arange(num_tasks) + 0.5)
    ax.set_xticklabels(
        [f"T{i + 1}" for i in range(num_tasks)],
        rotation=35,
        # ha="right",
        # rotation_mode="anchor",
    )
    ax.set_yticks(np.arange(num_tasks) + 0.5)
    ax.set_yticklabels([f"T{i + 1}" for i in range(num_tasks)])
    ax.set_xlabel("Predicted Task")
    ax.set_ylabel("Ground-Truth Task")
    # ax.tick_params(axis="x", width=0.95, length=3.2, colors=TEXT_COLOR)
    # ax.tick_params(axis="y", width=0.95, length=3.2, colors=TEXT_COLOR)
    # set_tick_bold(ax, fontsize=TICK_LABEL_FONTSIZE)

    highlight_col = 6
    # Visual cue for routing collapse: many tasks routed into T7 branch.
    collapse_rect = Rectangle(
        (highlight_col, 0),
        1,
        num_tasks,
        fill=False,
        # edgecolor="#2F5D9B",
        linewidth=1.2,
        linestyle="-",
        zorder=6,
    )
    ax.add_patch(collapse_rect)

    for row_idx in range(num_tasks):
        value = final_confusion[row_idx, highlight_col]
        ax.text(
            highlight_col + 0.5,
            row_idx + 0.5,
            format_heatmap_value(value),
            ha="center",
            va="center",
            color=heatmap_text_color(im, float(value)),
            fontsize=VALUE_LABEL_FONTSIZE,
            fontweight="bold",
            zorder=5,
        )

    # ax.text(
    #     0.25,
    #     0.5,
    #     "Most tasks \n routed to T7",
    #     transform=ax.transAxes,
    #     ha="center",
    #     va="center",
    #     bbox=dict(
    #         boxstyle="round,pad=0.3", facecolor="white", edgecolor="none", alpha=0.8
    #     ),
    #     zorder=7,
    # )
    ax.annotate(
        "Collapsed\nRouting",
        xy=(highlight_col, num_tasks * 0.50),
        transform=ax.transAxes,
        xycoords="data",
        ha="center",
        xytext=(0.25, 0.50),
        textcoords=ax.transAxes,
        bbox=dict(
            boxstyle="round,pad=0.3", facecolor="white", edgecolor="none", alpha=0.6
        ),
        arrowprops=dict(arrowstyle="->", lw=1.2),
        zorder=7,
    )

    for spine in ax.spines.values():
        spine.set_visible(False)
    ax.set_frame_on(False)
    ax.patch.set_linewidth(0.0)
    ax.patch.set_edgecolor("none")
    draw_panel_label(ax, "(a)")


# =========================
# 七、Panel (b): Inferred vs Oracle AUC 对比
# 作用：比较模型推断得到的 AUC 与 oracle 上界，并标出差值。
# =========================


def draw_oracle_panel(fig, outer_spec) -> None:
    # 画中间柱状图：左柱是 inferred，右柱是 oracle，中间叠加显示提升空间。
    _, infer_auc_matrix, oracle_auc_matrix, _ = load_confusion_data()

    num_tasks = infer_auc_matrix.shape[0]
    task_ids = np.arange(1, num_tasks + 1)
    x_positions = np.arange(num_tasks, dtype=np.float32) * 1.50 + 1.0
    infer_final = infer_auc_matrix[-1] * 100.0
    oracle_final = oracle_auc_matrix[-1] * 100.0
    gap_to_oracle = np.clip(oracle_final - infer_final, a_min=0.0, a_max=None)
    width = 0.60

    ax = fig.add_subplot(outer_spec)
    # ax.set_anchor("S")
    # ax.set_facecolor(BAR_BACKGROUND_COLOR)
    ax.patch.set_facecolor("C1")
    ax.patch.set_alpha(0.1)
    ax.grid(axis="y", linestyle="--", linewidth=0.85, color=GRID_COLOR, zorder=0)
    ax.set_axisbelow(True)

    ax.bar(
        x_positions - width / 2,
        infer_final,
        width=width,
        label="Inferred",
        color=INFERRED_BAR_COLOR,
        edgecolor=BAR_EDGE_COLOR,
        linewidth=0.95,
        hatch="/",
        zorder=3,
    )
    ax.bar(
        x_positions - width / 2,
        gap_to_oracle,
        width=width,
        bottom=infer_final,
        label="Uneven Oracle Gains",
        color=BAR_GAIN_COLOR,
        edgecolor=BAR_EDGE_COLOR,
        linewidth=0.95,
        zorder=4,
    )
    ax.bar(
        x_positions + width / 2,
        oracle_final,
        width=width,
        label="Oracle",
        color=ORACLE_BAR_COLOR,
        edgecolor=BAR_EDGE_COLOR,
        linewidth=0.95,
        hatch=".",
        zorder=3,
    )

    ax.set_xlabel("Ground-Truth Task")
    ax.set_ylabel("Macro-AUC (%)")
    ax.set_ylim(0.0, 100.0)
    ax.set_xlim(x_positions[0] - 0.86, x_positions[-1] + 0.86)
    ax.set_xticks(x_positions)
    ax.set_xticklabels([f"T{task_id}" for task_id in task_ids], rotation=35)
    ax.set_yticks(np.arange(0.0, 101.0, 20.0))
    # ax.tick_params(axis="x", direction="out")
    # ax.tick_params(axis="y", which="both", direction="out", left=True, right=False)
    ax.yaxis.set_ticks_position("left")
    ax.spines["top"].set_visible(False)
    ax.spines["right"].set_visible(False)
    # ax.spines["left"].set_linewidth(1.05)
    # ax.spines["bottom"].set_linewidth(1.05)
    # set_tick_bold(ax, fontsize=TICK_LABEL_FONTSIZE)

    y_offsets = {
        1: 0.0,
        2: 0.0,
        4: 0.0,
        5: 5.6,
        6: 0.8,
        7: 2.8,
        8: 0.8,
        9: 0.0,
        10: 0.0,
    }
    x_offsets = {
        1: -0.05,
        2: 0.04,
        4: -0.05,
        5: 0.06,
        6: 0.25,
        7: 0.05,
        8: -0.04,
        9: 0.05,
        10: 0.25,
    }

    for task_id, x_pos, infer_val, gap_val in zip(
        task_ids, x_positions - width / 2, infer_final, gap_to_oracle
    ):
        if gap_val <= 0.05:
            continue
        y = min(infer_val + gap_val + 1 + y_offsets.get(int(task_id), 0.0), 99.0)
        x = x_pos + x_offsets.get(int(task_id), 0.0)
        x = x_pos
        y = infer_val + gap_val + 2 
        ax.text(
            x,
            y,
            f"+{gap_val:.1f}",
            ha="center",
            va="bottom",
            # color=BAR_GAIN_COLOR,
            fontsize=12,
            zorder=6,
        )

    handles, labels = ax.get_legend_handles_labels()
    label_to_handle = {label: handle for handle, label in zip(handles, labels)}
    ordered_labels = ["Inferred", "Oracle", "Uneven Oracle Gains"]
    ordered_handles = [label_to_handle[label] for label in ordered_labels if label in label_to_handle]
    legend = ax.legend(
        ordered_handles,
        ordered_labels,
        frameon=False,
        loc="upper left",
        bbox_to_anchor=(0.015, 0.985),
        borderaxespad=0.0,
        handlelength=1.05,
        handletextpad=0.38,
        labelspacing=0.20,
        ncol=2,
    )
    # ax.text(
    #     0.985,
    #     0.92,
    #     "Uneven Oracle Gains",
    #     transform=ax.transAxes,
    #     ha="right",
    #     va="top",
    #     fontsize=11,
    #     color="#4A4A4A",
    #     style="italic",
    #     zorder=7,
    # )
    # for text in legend.get_texts():
    #     text.set_fontweight("bold")

    draw_panel_label(ax, "(b)")


# =========================
# 八、Panel (c) 的嵌入散点小图
# 作用：分别画出 w/o prompt 与 w/ prompt 下 ISC 和 LVH 的分布变化。
# =========================


def draw_inset_panel(ax, pair_plot: dict[str, object], condition: str) -> None:
    # 先画背景样本，再高亮指定类别对，并连接两类中心点。
    pair_a, pair_b = pair_plot["pair_labels"]
    rows = pair_plot["rows_by_condition"][condition]
    background_rows = [row for row in rows if not row["is_pair_non_easy"]]
    highlight_rows = [row for row in rows if row["is_pair_non_easy"]]
    cond_colors = INSET_CONDITION_COLORS.get(condition, INSET_CONDITION_COLORS["prompt"])

    ax.scatter(
        [row["proj_x"] for row in background_rows],
        [row["proj_y"] for row in background_rows],
        s=7,
        marker="o",
        color=BACKGROUND_COLOR,
        alpha=0.25,
        edgecolors="none",
        zorder=1,
    )

    subset_a = [row for row in highlight_rows if row["true_label"] == pair_a]
    ax.scatter(
        [row["proj_x"] for row in subset_a],
        [row["proj_y"] for row in subset_a],
        s=16,
        marker="o",
        color=cond_colors["A"],
        alpha=0.85,
        edgecolors="white",
        linewidths=0.22,
        zorder=2,
    )

    subset_b = [row for row in highlight_rows if row["true_label"] == pair_b]
    ax.scatter(
        [row["proj_x"] for row in subset_b],
        [row["proj_y"] for row in subset_b],
        s=18,
        marker="x",
        color=cond_colors["B"],
        alpha=0.9,
        linewidths=1.0,
        zorder=2,
    )

    c1 = pair_plot["centers"][condition][pair_a]
    c2 = pair_plot["centers"][condition][pair_b]
    ax.plot(
        [c1[0], c2[0]],
        [c1[1], c2[1]],
        linestyle=(0, (2.0, 2.0)),
        color="#8E8E8E",
        linewidth=0.78,
        zorder=2,
    )
    ax.scatter(
        [c1[0]],
        [c1[1]],
        s=24,
        marker="o",
        color=cond_colors["A_center"],
        edgecolors="#2E2E2E",
        linewidths=0.45,
        zorder=3,
    )
    ax.scatter(
        [c2[0]],
        [c2[1]],
        s=28,
        marker="X",
        color=cond_colors["B_center"],
        edgecolors="#2E2E2E",
        linewidths=0.40,
        zorder=3,
    )

    ax.set_xlim(*pair_plot["xlim"])
    ax.set_ylim(*pair_plot["ylim"])
    ax.set_xticks([])
    ax.set_yticks([])
    for side in ["top", "right", "left", "bottom"]:
        ax.spines[side].set_visible(False)
    ax.set_facecolor("none")


# =========================
# 九、Panel (c): 不同难度样本的 margin gain
# 作用：主图是三组柱状图，嵌入图用来解释 near/hard 样本的类别分布变化。
# =========================


def draw_margin_panel(fig, outer_spec) -> None:
    # 画右侧主柱图，并在柱图中嵌入 ISC vs LVH 的二维投影示意。
    from matplotlib.lines import Line2D
    from matplotlib.patches import FancyBboxPatch
    import matplotlib.patheffects as pe

    pair_plot = build_pair_plot(load_pair_rows())

    ax = fig.add_subplot(outer_spec)
    # ax.set_anchor("S")
    # ax.set_facecolor("C2")
    ax.patch.set_facecolor('C2')
    ax.patch.set_alpha(0.1)

    xs = [0.10, 0.45, 0.78]
    heights = [row["positive_rate"] * 100.0 for row in BAR_STATS]
    bar_width = 0.125

    bars = ax.bar(
        xs,
        heights,
        width=bar_width,
        color=MARGIN_BAR_COLORS,
        edgecolor=MARGIN_HATCH_EDGE_COLOR,
        linewidth=0.95,
        zorder=3,
    )
    for bar, hatch in zip(bars, MARGIN_BAR_HATCHES):
        bar.set_hatch(hatch)

    ax.set_ylabel(
        "Positive Margin Gain (%)",
        color=MARGIN_TEXT_COLOR,
        labelpad=5,
    )
    ax.set_ylim(0.0, 100.0)
    ax.set_xlim(-0.03, 0.92)
    ax.set_yticks([0, 20, 40, 60, 80, 100])
    ax.set_xticks(xs)

    xtick_labels = [
        "Correct\n($=1$)\n$n=1706$",
        "Near\n($=2-5$)\n$n=146$",
        "Hard\n($>5$)\n$n=306$",
    ]
    main_tick_texts = ax.set_xticklabels(xtick_labels, ha="right")
    for tick in main_tick_texts:
        tick.set_color(MARGIN_TEXT_COLOR)
        # tick.set_fontweight("bold")
        # tick.set_fontsize(11.2)
        tick.set_ha("center")
        tick.set_linespacing(0.95)

    ax.grid(axis="y", linestyle="-", color=MARGIN_GRID_COLOR, linewidth=0.80, zorder=0)
    ax.set_axisbelow(True)
    # ax.tick_params(
    #     axis="y",
    #     which="both",
    #     direction="out",
    #     length=3.5,
    #     width=0.95,
    #     colors=MARGIN_TEXT_COLOR,
    #     pad=3.0,
    # )
    # ax.tick_params(
    #     axis="x", direction="out", length=0, pad=8.0, colors=MARGIN_TEXT_COLOR
    # )
    ax.yaxis.set_ticks_position("left")
    for spine in ax.spines.values():
        spine.set_linewidth(1.05)
        spine.set_color(MARGIN_SPINE_COLOR)
    # set_tick_bold(ax, fontsize=TICK_LABEL_FONTSIZE)

    for x, pct in zip(xs, heights):
        ax.text(
            x,
            pct + 2,
            f"{pct:.1f}",
            ha="center",
            va="bottom",
            fontsize=12,
            zorder=6,
        )

    inset_x, inset_y, inset_w, inset_h = 0.1, 0.45, 0.8, 0.4
    inset_frame = FancyBboxPatch(
        (inset_x, inset_y),
        inset_w,
        inset_h,
        boxstyle="round,pad=0.005,rounding_size=0.010",
        transform=ax.transAxes,
        facecolor="white",
        edgecolor="#D0D6DC",
        alpha=0.9,
        linewidth=0.90,
        zorder=4.0,
    )
    inset_frame.set_path_effects(
        [
            pe.SimplePatchShadow(offset=(0.9, -0.9), shadow_rgbFace=(0, 0, 0, 0.08)),
            pe.Normal(),
        ]
    )
    ax.add_patch(inset_frame)

    ax.text(
        inset_x + inset_w / 2.0,
        inset_y + inset_h - 0.024,
        "ISC vs LVH",
        transform=ax.transAxes,
        ha="center",
        va="top",
        fontsize=INSET_TITLE_FONTSIZE + 0.5,
        color=MARGIN_TEXT_COLOR,
        zorder=7,
    )
    ax.text(
        inset_x + 0.180,
        inset_y + inset_h - 0.080,
        "w/o prompt",
        transform=ax.transAxes,
        ha="center",
        va="top",
        fontsize=INSET_SUBTITLE_FONTSIZE,
        color=MARGIN_TEXT_COLOR,
        zorder=10,
        bbox=dict(
            boxstyle="round,pad=0.12", facecolor=(1, 1, 1, 0.72), edgecolor="none"
        ),
    )
    ax.text(
        inset_x + inset_w - 0.180,
        inset_y + inset_h - 0.080,
        "w/ prompt",
        transform=ax.transAxes,
        ha="center",
        va="top",
        fontsize=INSET_SUBTITLE_FONTSIZE,
        color=MARGIN_TEXT_COLOR,
        zorder=10,
        bbox=dict(
            boxstyle="round,pad=0.12", facecolor=(1, 1, 1, 0.72), edgecolor="none"
        ),
    )

    ax_left = ax.inset_axes([inset_x + 0.06, inset_y + 0.12, 0.285, 0.145], zorder=7)
    ax_right = ax.inset_axes([inset_x + 0.45, inset_y + 0.12, 0.285, 0.145], zorder=7)
    draw_inset_panel(ax_left, pair_plot, "noprompt")
    draw_inset_panel(ax_right, pair_plot, "prompt")

    for mini_ax in [ax_left, ax_right]:
        mini_ax.set_title("")
        mini_ax.set_xticks([])
        mini_ax.set_yticks([])
        mini_ax.tick_params(width=0.0, length=0.0)
        for text in mini_ax.texts:
            text.set_visible(False)
        for spine in mini_ax.spines.values():
            spine.set_linewidth(0.65)

    ax.text(
        inset_x + inset_w / 2.0,
        inset_y + 0.01,
        "0/92 rescued \n gap 0.0094 $\\rightarrow$ 0.0074",
        transform=ax.transAxes,
        ha="center",
        va="bottom",
        fontsize=INSET_SUMMARY_FONTSIZE,
        color="#4F4F4F",
        zorder=7,
    )

    x_left_corner = xs[1] - bar_width / 2.0
    x_right_corner = xs[1] + bar_width / 2.0
    y_top = heights[1]
    left_corner_axes = ax.transAxes.inverted().transform(
        ax.transData.transform((x_left_corner, y_top))
    )
    right_corner_axes = ax.transAxes.inverted().transform(
        ax.transData.transform((x_right_corner, y_top))
    )
    left_target = (inset_x + 0.12, inset_y)
    right_target = (inset_x + inset_w - 0.12, inset_y)

    guide1 = Line2D(
        [left_corner_axes[0], left_target[0]],
        [left_corner_axes[1], left_target[1]],
        transform=ax.transAxes,
        color=MARGIN_GUIDE_COLOR,
        linewidth=0.80,
        linestyle=(0, (2.0, 2.0)),
        zorder=2,
    )
    guide2 = Line2D(
        [right_corner_axes[0], right_target[0]],
        [right_corner_axes[1], right_target[1]],
        transform=ax.transAxes,
        color=MARGIN_GUIDE_COLOR,
        linewidth=0.80,
        linestyle=(0, (2.0, 2.0)),
        zorder=2,
    )
    ax.add_line(guide1)
    ax.add_line(guide2)

    ax.spines["top"].set_visible(False)
    ax.spines["right"].set_visible(False)

    draw_panel_label(ax, "(c)")


# =========================
# 十、输出与主流程
# 作用：拼好三联图并导出为 PNG/PDF。
# =========================


def save_outputs(fig, output_png: Path, output_pdf: Path, dpi: int) -> None:
    # 确保输出目录存在，再保存两种格式。
    output_png.parent.mkdir(parents=True, exist_ok=True)
    output_pdf.parent.mkdir(parents=True, exist_ok=True)
    fig.savefig(output_png, dpi=dpi, bbox_inches="tight", pad_inches=0.020)
    fig.savefig(output_pdf, bbox_inches="tight", pad_inches=0.020)


def main() -> None:
    # 主入口：解析参数 -> 配置风格 -> 创建三联图 -> 保存结果。
    args = parse_args()
    output_png = Path(args.output_png).expanduser().resolve()
    output_pdf = Path(args.output_pdf).expanduser().resolve()

    configure_matplotlib()

    import matplotlib.pyplot as plt

    fig = plt.figure(figsize=(args.fig_width, args.fig_height), facecolor="white")
    outer = fig.add_gridspec(
        1,
        4,
        width_ratios=[3, 0.10, 5.8, 2],
        wspace=0.32,
    )

    draw_confusion_panel(fig, outer[0], outer[1])
    draw_oracle_panel(fig, outer[2])
    draw_margin_panel(fig, outer[3])

    save_outputs(fig, output_png=output_png, output_pdf=output_pdf, dpi=args.dpi)
    plt.close(fig)

    print("Saved self-contained one-row figure:")
    print(f"  PNG: {output_png}")
    print(f"  PDF: {output_pdf}")

    import os

    os.system(f"pdfcrop {output_pdf} {output_pdf}")


if __name__ == "__main__":
    main()
