15
15
"hnsw" ,
16
16
}
17
17
18
-
19
18
def custom_filter (row ):
20
- # All ef values that are lowern tha the `limit` are set to the `limit`
21
19
if row ['limit' ] == 100 and row ['ef' ] < 90 :
22
20
return False
23
21
return True
24
22
25
-
26
23
def get_datapoints (dataset :str , path : str ):
27
24
datapoints = []
28
25
for filename in glob .glob (os .path .join (path , "*.json" )):
@@ -31,76 +28,126 @@ def get_datapoints(dataset:str, path: str):
31
28
datapoints += parsed [1 :]
32
29
df = pd .DataFrame (datapoints )
33
30
return df [
34
- (df ["dataset_file" ] == dataset ) # filter for a specific dataset
35
- & (df ['run' ].isin (RUNS )) # remove PQ/BQ/SQ results
31
+ (df ["dataset_file" ] == dataset )
32
+ & (df ['run' ].isin (RUNS ))
36
33
& (df ["maxConnections" ] == MAX_CONNECTIONS )
37
34
& (df ["efConstruction" ] == EF_CONSTRUCTION )
38
35
& (df .apply (custom_filter , axis = 1 ))
39
36
]
40
37
41
-
42
- def create_plot (results_df : pd .DataFrame ):
43
-
38
+ def create_plot (results_df : pd .DataFrame , mode = 'light' ):
44
39
dataset = results_df ["dataset_file" ].iloc [0 ]
45
-
46
- sns .set_theme (
47
- style = 'whitegrid' ,
48
- font_scale = 1.2 ,
49
- rc = {
50
- # 'axes.grid': True,
51
- # 'savefig.transparent': True,
52
- # 'axes.facecolor': color,
53
- # 'figure.facecolor': color,
54
- # 'axes.edgecolor': color,
55
- # 'grid.color': color,
56
- # 'ytick.labelcolor': color,
57
- # 'xtick.labelcolor': color,
58
- }
59
- )
60
- plot = sns .relplot (
61
- linewidth = 3 ,
62
- height = 7 ,
63
- aspect = 1.5 ,
64
- marker = "o" ,
65
- dashes = False ,
66
- data = results_df ,
67
- kind = "line" ,
68
- x = "recall" ,
69
- y = "qps" ,
70
- hue = "limit" ,
71
- style = "limit" ,
72
- palette = ["b" , "g" ],
40
+
41
+ # Set custom colors for limits
42
+ color_map = {
43
+ 100 : '#098f73' ,
44
+ 10 : '#2b17e7'
45
+ }
46
+
47
+ # Configure plot style based on mode
48
+ plt .style .use ('default' )
49
+ plt .rcParams ['font.family' ] = ['Arial' ]
50
+
51
+ # Create new figure
52
+ fig , ax = plt .subplots (figsize = (10.5 , 7 ))
53
+
54
+ # Set colors based on mode
55
+ if mode == 'dark' :
56
+ text_color = 'white'
57
+ grid_color = '#333333'
58
+ spine_color = '#444444'
59
+ bg_color = '#000000'
60
+ else : # light mode
61
+ text_color = 'black'
62
+ grid_color = '#CCCCCC'
63
+ spine_color = '#DDDDDD'
64
+ bg_color = '#ffffff'
65
+
66
+ # Configure plot background
67
+ ax .set_facecolor (bg_color )
68
+ fig .patch .set_facecolor (bg_color )
69
+
70
+ # Plot lines for each limit value
71
+ for limit in sorted (results_df ['limit' ].unique ()):
72
+ data = results_df [results_df ['limit' ] == limit ]
73
+ ax .plot (data ['recall' ], data ['qps' ],
74
+ color = color_map [limit ],
75
+ linewidth = 1.5 ,
76
+ marker = 'o' ,
77
+ markersize = 4 ,
78
+ label = f'Limit: { limit } ' )
79
+ for x , y , ef in zip (data ['recall' ], data ['qps' ], data ['ef' ]):
80
+ ax .annotate (f'ef={ ef } ' ,
81
+ xy = (x , y ),
82
+ xytext = (3 , 7 ), # 5 points vertical offset
83
+ textcoords = 'offset points' ,
84
+ ha = 'center' , # horizontal alignment
85
+ va = 'bottom' , # vertical alignment
86
+ fontsize = 9 ,
87
+ color = text_color )
88
+
89
+ # Customize axes
90
+ ax .set_xlabel ('Recall' , fontsize = 11 , fontweight = "bold" , labelpad = 5 , color = text_color )
91
+ ax .set_ylabel ('QPS' , fontsize = 11 , fontweight = "bold" , labelpad = 5 , color = text_color )
92
+
93
+ # Format axis ticks
94
+ ax .set_xlim (left = None , right = 1 )
95
+ ax .set_ylim (bottom = 0 , top = None )
96
+
97
+ # Set tick colors
98
+ ax .tick_params (colors = text_color , labelsize = 10 )
99
+ for label in ax .get_xticklabels () + ax .get_yticklabels ():
100
+ label .set_color (text_color )
101
+
102
+ # Customize grid
103
+ ax .grid (True , linestyle = '--' , alpha = 0.7 , color = grid_color )
104
+ ax .set_axisbelow (True )
105
+
106
+ # Add title
107
+ plt .title (f"Query Performance { dataset .replace ('.hdf5' , '' )} (efConstruction={ EF_CONSTRUCTION } , maxConnections={ MAX_CONNECTIONS } )" ,
108
+ pad = 20 ,
109
+ fontdict = {'family' : 'Arial' ,
110
+ 'weight' : 'bold' ,
111
+ 'size' : 11 },
112
+ color = text_color )
113
+
114
+ # Customize legend
115
+ legend = ax .legend (
116
+ loc = 'upper right' ,
117
+ frameon = True ,
118
+ fancybox = True ,
119
+ framealpha = 0 ,
120
+ edgecolor = spine_color ,
121
+ fontsize = 10
73
122
)
74
- plot .set_axis_labels (
75
- x_var = "Recall, [%]" ,
76
- y_var = "QPS" ,
123
+ # Set legend text color
124
+ plt .setp (legend .get_texts (), color = text_color )
125
+
126
+ # Set spines visibility and color
127
+ for spine in ax .spines .values ():
128
+ spine .set_visible (True )
129
+ spine .set_color (spine_color )
130
+
131
+ # Adjust layout and save
132
+ plt .tight_layout ()
133
+ mode_suffix = 'dark' if mode == 'dark' else 'light'
134
+ plt .savefig (
135
+ f"{ dataset .split ('.' )[0 ]} -{ mode_suffix } .png" ,
136
+ dpi = 300 ,
137
+ bbox_inches = 'tight' ,
138
+ transparent = False
77
139
)
78
- plot .figure .subplots_adjust (top = 0.85 )
79
- plot .figure .suptitle (
80
- f"Query Performance, { dataset } " ,
81
- weight = "bold" ,
82
-
83
- )
84
- sns .move_legend (
85
- plot ,
86
- "lower center" ,
87
- bbox_to_anchor = (.5 , .84 ),
88
- ncol = 3 ,
89
- title = "Limit: " ,
90
- frameon = False ,
91
- )
92
-
93
-
94
- plot .axes [0 ][0 ].get_xaxis ().set_major_formatter (tkr .FuncFormatter (lambda x , _ : f'{ x * 100 :.0f} ' ))
95
- plot .axes [0 ][0 ].get_yaxis ().set_major_formatter (tkr .StrMethodFormatter ('{x:,.0f}' ))
96
- plt .savefig (f"{ dataset .split ('.' )[0 ]} .png" , bbox_inches = 'tight' )
140
+ plt .close ()
97
141
98
142
if __name__ == "__main__" :
99
143
parser = argparse .ArgumentParser (description = "Collate ann results into markdown tables." )
100
144
parser .add_argument ('-d' , '--dataset' , required = True , help = "The dataset file to filter by" )
101
145
parser .add_argument ('-r' , '--results' , default = "./results" , help = "The directory containing benchmark results" )
102
146
args = parser .parse_args ()
103
147
104
- create_plot (
105
- get_datapoints (args .dataset , os .path .expanduser (args .results )),
106
- )
148
+ # Get the data
149
+ data = get_datapoints (args .dataset , os .path .expanduser (args .results ))
150
+
151
+ # Create both light and dark mode versions
152
+ create_plot (data , mode = 'light' )
153
+ create_plot (data , mode = 'dark' )
0 commit comments