Current task: —

E-022b-valley-analysis.py

Experiments: E-022b · script updated 08-19-2026

E-022b-valley.csv — 87.2 KB, updated 08-19-2026

page 1 of 10 · 500/page · 4600 rows next →
# azlogK
2 4 14.000 0.434704
3 4 14.050 0.143554
4 4 14.100 -0.068293
5 4 14.150 -0.108351
6 4 14.200 0.045776
7 4 14.250 0.317268
8 4 14.300 0.618833
9 4 14.350 0.903235
10 4 14.400 1.153573
11 4 14.450 1.366670
12 4 14.500 1.544336
13 4 14.550 1.689838
14 4 14.600 1.806647
15 4 14.650 1.898055
16 4 14.700 1.967118
17 4 14.750 2.016710
18 4 14.800 2.049599
19 4 14.850 2.068523
20 4 14.900 2.076237
21 4 14.950 2.075521
22 4 15.000 2.069138
23 4 15.050 2.059743
24 4 15.100 2.049737
25 4 15.150 2.041107
26 4 15.200 2.035267
27 4 15.250 2.032969
28 4 15.300 2.034297
29 4 15.350 2.038751
30 4 15.400 2.045424
31 4 15.450 2.053199
32 4 15.500 2.060952
33 4 15.550 2.067712
34 4 15.600 2.072772
35 4 15.650 2.075746
36 4 15.700 2.076577
37 4 15.750 2.075503
38 4 15.800 2.072996
39 4 15.850 2.069680
40 4 15.900 2.066226
41 4 15.950 2.063261
42 4 16.000 2.061274
43 4 16.050 2.060556
44 4 16.100 2.061167
45 4 16.150 2.062952
46 4 16.200 2.065578
47 4 16.250 2.068604
48 4 16.300 2.071560
49 4 16.350 2.074023
50 4 16.400 2.075673
51 4 16.450 2.076339
52 4 16.500 2.076013
53 4 16.550 2.074839
54 4 16.600 2.073083
55 4 16.650 2.071089
56 4 16.700 2.069221
57 4 16.750 2.067802
58 4 16.800 2.067069
59 4 16.850 2.067130
60 4 16.900 2.067958
61 4 16.950 2.069398
62 4 17.000 2.071197
63 4 17.050 2.073052
64 4 17.100 2.074659
65 4 17.150 2.075764
66 4 17.200 2.076202
67 4 17.250 2.075921
68 4 17.300 2.074988
69 4 17.350 2.073576
70 4 17.400 2.071935
71 4 17.450 2.070353
72 4 17.500 2.069104
73 4 17.550 2.068404
74 4 17.600 2.068376
75 4 17.650 2.069026
76 4 17.700 2.070242
77 4 17.750 2.071814
78 4 17.800 2.073469
79 4 17.850 2.074914
80 4 17.900 2.075889
81 4 17.950 2.076209
82 4 18.000 2.075793
83 4 18.050 2.074680
84 4 18.100 2.073029
85 4 18.150 2.071094
86 4 18.200 2.069185
87 4 18.250 2.067620
88 4 18.300 2.066671
89 4 18.350 2.066514
90 4 18.400 2.067194
91 4 18.450 2.068613
92 4 18.500 2.070540
93 4 18.550 2.072644
94 4 18.600 2.074544
95 4 18.650 2.075873
96 4 18.700 2.076335
97 4 18.750 2.075759
98 4 18.800 2.074131
99 4 18.850 2.071610
100 4 18.900 2.068510
101 4 18.950 2.065269
102 4 19.000 2.062382
103 4 19.050 2.060325
104 4 19.100 2.059472
105 4 19.150 2.060019
106 4 19.200 2.061937
107 4 19.250 2.064950
108 4 19.300 2.068570
109 4 19.350 2.072152
110 4 19.400 2.074988
111 4 19.450 2.076409
112 4 19.500 2.075892
113 4 19.550 2.073147
114 4 19.600 2.068189
115 4 19.650 2.061373
116 4 19.700 2.053395
117 4 19.750 2.045236
118 4 19.800 2.038055
119 4 19.850 2.033030
120 4 19.900 2.031146
121 4 19.950 2.032987
122 4 20.000 2.038552
123 4 20.050 2.047152
124 4 20.100 2.057411
125 4 20.150 2.067354
126 4 20.200 2.074570
127 4 20.250 2.076384
128 4 20.300 2.070006
129 4 20.350 2.052640
130 4 20.400 2.021522
131 4 20.450 1.973925
132 4 20.500 1.907107
133 4 20.550 1.818242
134 4 20.600 1.704341
135 4 20.650 1.562193
136 4 20.700 1.388403
137 4 20.750 1.179724
138 4 20.800 0.934152
139 4 20.850 0.654037
140 4 20.900 0.353869
141 4 20.950 0.075732
142 4 21.000 -0.098282
143 4 21.050 -0.085695
144 4 21.100 0.106035
145 4 21.150 0.389245
146 4 21.200 0.686764
147 4 21.250 0.961354
148 4 21.300 1.200921
149 4 21.350 1.404059
150 4 21.400 1.573096
151 4 21.450 1.711365
152 4 21.500 1.822257
153 4 21.550 1.908937
154 4 21.600 1.974328
155 4 21.650 2.021162
156 4 21.700 2.052061
157 4 21.750 2.069601
158 4 21.800 2.076365
159 4 21.850 2.074953
160 4 21.900 2.067952
161 4 21.950 2.057868
162 4 22.000 2.047006
163 4 22.050 2.037329
164 4 22.100 2.030314
165 4 22.150 2.026850
166 4 22.200 2.027204
167 4 22.250 2.031063
168 4 22.300 2.037663
169 4 22.350 2.045953
170 4 22.400 2.054777
171 4 22.450 2.063035
172 4 22.500 2.069809
173 4 22.550 2.074443
174 4 22.600 2.076589
175 4 22.650 2.076213
176 4 22.700 2.073575
177 4 22.750 2.069188
178 4 22.800 2.063754
179 4 22.850 2.058078
180 4 22.900 2.052979
181 4 22.950 2.049181
182 4 23.000 2.047225
183 4 23.050 2.047394
184 4 23.100 2.049667
185 4 23.150 2.053728
186 4 23.200 2.059002
187 4 23.250 2.064736
188 4 23.300 2.070093
189 4 23.350 2.074257
190 4 23.400 2.076533
191 4 23.450 2.076427
192 4 23.500 2.073717
193 4 23.550 2.068493
194 4 23.600 2.061177
195 4 23.650 2.052508
196 4 23.700 2.043488
197 4 23.750 2.035291
198 4 23.800 2.029112
199 4 23.850 2.025993
200 4 23.900 2.026630
201 4 23.950 2.031198
202 4 24.000 2.039247
203 4 24.050 2.049675
204 4 24.100 2.060795
205 4 24.150 2.070459
206 4 24.200 2.076222
207 4 24.250 2.075482
208 4 24.300 2.065594
209 4 24.350 2.043931
210 4 24.400 2.007895
211 4 24.450 1.954896
212 4 24.500 1.882288
213 4 24.550 1.787298
214 4 24.600 1.666951
215 4 24.650 1.518026
216 4 24.700 1.337149
217 4 24.750 1.121228
218 4 24.800 0.868857
219 4 24.850 0.584131
220 4 24.900 0.285880
221 4 24.950 0.024221
222 4 25.000 -0.113127
223 4 25.050 -0.056764
224 4 25.100 0.162915
225 4 25.150 0.454535
226 4 25.200 0.749731
227 4 25.250 1.018115
228 4 25.300 1.250653
229 4 25.350 1.447000
230 4 25.400 1.609750
231 4 25.450 1.742231
232 4 25.500 1.847749
233 4 25.550 1.929395
234 4 25.600 1.990045
235 4 25.650 2.032429
236 4 25.700 2.059215
237 4 25.750 2.073072
238 4 25.800 2.076710
239 4 25.850 2.072879
240 4 25.900 2.064311
241 4 25.950 2.053614
242 4 26.000 2.043115
243 4 26.050 2.034687
244 4 26.100 2.029598
245 4 26.150 2.028422
246 4 26.200 2.031056
247 4 26.250 2.036828
248 4 26.300 2.044680
249 4 26.350 2.053386
250 4 26.400 2.061747
251 4 26.450 2.068759
252 4 26.500 2.073713
253 4 26.550 2.076246
254 4 26.600 2.076354
255 4 26.650 2.074347
256 4 26.700 2.070795
257 4 26.750 2.066428
258 4 26.800 2.062036
259 4 26.850 2.058358
260 4 26.900 2.055971
261 4 26.950 2.055221
262 4 27.000 2.056178
263 4 27.050 2.058642
264 4 27.100 2.062186
265 4 27.150 2.066243
266 4 27.200 2.070193
267 4 27.250 2.073462
268 4 27.300 2.075603
269 4 27.350 2.076352
270 4 27.400 2.075656
271 4 27.450 2.073680
272 4 27.500 2.070771
273 4 27.550 2.067415
274 4 27.600 2.064156
275 4 27.650 2.061522
276 4 27.700 2.059937
277 4 27.750 2.059656
278 4 27.800 2.060722
279 4 27.850 2.062959
280 4 27.900 2.066000
281 4 27.950 2.069347
282 4 28.000 2.072448
283 4 28.050 2.074782
284 4 28.100 2.075939
285 4 28.150 2.075681
286 4 28.200 2.073980
287 4 28.250 2.071031
288 4 28.300 2.067229
289 4 28.350 2.063123
290 4 28.400 2.059337
291 4 28.450 2.056478
292 4 28.500 2.055031
293 4 28.550 2.055274
294 4 28.600 2.057212
295 4 28.650 2.060563
296 4 28.700 2.064783
297 4 28.750 2.069144
298 4 28.800 2.072835
299 4 28.850 2.075080
300 4 28.900 2.075255
301 4 28.950 2.072991
302 4 29.000 2.068246
303 4 29.050 2.061348
304 4 29.100 2.052998
305 4 29.150 2.044220
306 4 29.200 2.036248
307 4 29.250 2.030361
308 4 29.300 2.027665
309 4 29.350 2.028862
310 4 29.400 2.034048
311 4 29.450 2.042597
312 4 29.500 2.053150
313 4 29.550 2.063708
314 4 29.600 2.071803
315 4 29.650 2.074685
316 4 29.700 2.069487
317 4 29.750 2.053342
318 4 29.800 2.023432
319 4 29.850 1.976990
320 4 29.900 1.911255
321 4 29.950 1.823398
322 4 30.000 1.710446
323 4 30.050 1.569217
324 4 30.100 1.396367
325 4 30.150 1.188699
326 4 30.200 0.944233
327 4 30.250 0.665200
328 4 30.300 0.365533
329 4 30.350 0.085779
330 4 30.400 -0.094253
331 4 30.450 -0.091776
332 4 30.500 0.090306
333 4 30.550 0.367255
334 4 30.600 0.661344
335 4 30.650 0.934107
336 4 30.700 1.172720
337 4 30.750 1.375476
338 4 30.800 1.544625
339 4 30.850 1.683521
340 4 30.900 1.795609
341 4 30.950 1.884115
342 4 31.000 1.951989
343 4 31.050 2.001948
344 4 31.100 2.036522
345 4 31.150 2.058105
346 4 31.200 2.068986
347 4 31.250 2.071362
348 4 31.300 2.067335
349 4 31.350 2.058885
350 4 31.400 2.047841
351 4 31.450 2.035847
352 4 31.500 2.024321
353 4 31.550 2.014434
354 4 31.600 2.007091
355 4 31.650 2.002925
356 4 31.700 2.002290
357 4 31.750 2.005256
358 4 31.800 2.011607
359 4 31.850 2.020824
360 4 31.900 2.032086
361 4 31.950 2.044269
362 4 32.000 2.055969
363 4 32.050 2.065532
364 4 32.100 2.071095
365 4 32.150 2.070640
366 4 32.200 2.062030
367 4 32.250 2.043044
368 4 32.300 2.011381
369 4 32.350 1.964659
370 4 32.400 1.900378
371 4 32.450 1.815878
372 4 32.500 1.708280
373 4 32.550 1.574446
374 4 32.600 1.411003
375 4 32.650 1.214583
376 4 32.700 0.982650
377 4 32.750 0.715854
378 4 32.800 0.424074
379 4 32.850 0.139372
380 4 32.900 -0.068274
381 4 32.950 -0.109780
382 4 33.000 0.038598
383 4 33.050 0.304875
384 4 33.100 0.603814
385 4 33.150 0.887738
386 4 33.200 1.138896
387 4 33.250 1.353507
388 4 33.300 1.533009
389 4 33.350 1.680446
390 4 33.400 1.799141
391 4 33.450 1.892279
392 4 33.500 1.962836
393 4 33.550 2.013615
394 4 33.600 2.047330
395 4 33.650 2.066678
396 4 33.700 2.074395
397 4 33.750 2.073276
398 4 33.800 2.066134
399 4 33.850 2.055722
400 4 33.900 2.044582
401 4 33.950 2.034867
402 4 34.000 2.028163
403 4 34.050 2.025368
404 4 34.100 2.026650
405 4 34.150 2.031524
406 4 34.200 2.039020
407 4 34.250 2.047896
408 4 34.300 2.056863
409 4 34.350 2.064771
410 4 34.400 2.070742
411 4 34.450 2.074250
412 4 34.500 2.075140
413 4 34.550 2.073617
414 4 34.600 2.070187
415 4 34.650 2.065575
416 4 34.700 2.060621
417 4 34.750 2.056162
418 4 34.800 2.052917
419 4 34.850 2.051379
420 4 34.900 2.051758
421 4 34.950 2.053954
422 4 35.000 2.057588
423 4 35.050 2.062074
424 4 35.100 2.066712
425 4 35.150 2.070804
426 4 35.200 2.073746
427 4 35.250 2.075112
428 4 35.300 2.074708
429 4 35.350 2.072595
430 4 35.400 2.069080
431 4 35.450 2.064679
432 4 35.500 2.060051
433 4 35.550 2.055902
434 4 35.600 2.052887
435 4 35.650 2.051501
436 4 35.700 2.051995
437 4 35.750 2.054321
438 4 35.800 2.058134
439 4 35.850 2.062827
440 4 35.900 2.067622
441 4 35.950 2.071678
442 4 36.000 2.074207
443 4 36.050 2.074589
444 4 36.100 2.072465
445 4 36.150 2.067804
446 4 36.200 2.060942
447 4 36.250 2.052578
448 4 36.300 2.043723
449 4 36.350 2.035596
450 4 36.400 2.029465
451 4 36.450 2.026437
452 4 36.500 2.027240
453 4 36.550 2.032029
454 4 36.600 2.040264
455 4 36.650 2.050688
456 4 36.700 2.061418
457 4 36.750 2.070090
458 4 36.800 2.074049
459 4 36.850 2.070504
460 4 36.900 2.056644
461 4 36.950 2.029701
462 4 37.000 1.986950
463 4 37.050 1.925672
464 4 37.100 1.843090
465 4 37.150 1.736281
466 4 37.200 1.602117
467 4 37.250 1.437263
468 4 37.300 1.238402
469 4 37.350 1.003051
470 4 37.400 0.731931
471 4 37.450 0.435091
472 4 37.500 0.145130
473 4 37.550 -0.066735
474 4 37.600 -0.110203
475 4 37.650 0.037604
476 4 37.700 0.302799
477 4 37.750 0.599618
478 4 37.800 0.880800
479 4 37.850 1.129083
480 4 37.900 1.341031
481 4 37.950 1.518316
482 4 38.000 1.664147
483 4 38.050 1.781970
484 4 38.100 1.875059
485 4 38.150 1.946438
486 4 38.200 1.998909
487 4 38.250 2.035125
488 4 38.300 2.057639
489 4 38.350 2.068955
490 4 38.400 2.071536
491 4 38.450 2.067790
492 4 38.500 2.060016
493 4 38.550 2.050330
494 4 38.600 2.040571
495 4 38.650 2.032202
496 4 38.700 2.026249
497 4 38.750 2.023265
498 4 38.800 2.023360
499 4 38.850 2.026263
500 4 38.900 2.031428
501 4 38.950 2.038136

E-022b-valley.json — 3.5 KB, updated 08-19-2026

JSON sidecar (click to expand)
{
  "experiment": "E-022b",
  "task": "2.10 analysis: K-diagonal valleys + mass concentration",
  "script": "research/numerics/scripts/E-022b-valley-analysis.py",
  "checks": {
    "V1_valleys_at_gamma": true,
    "V2_mass_concentrated": true,
    "V4_fit_quality": true
  },
  "key_values": {
    "4": {
      "valley_depth": 2.1593140478568413,
      "logK_at_gamma": -0.106956845297883,
      "logK_at_midpoints": 2.0523572025589583,
      "mass_frac_pm0.1": 0.6338714893637662,
      "uniform_expectation": 0.09000000000000001,
      "mass_ratio_vs_uniform": 7.043016548486291,
      "within_bin_meanlogw": {
        "z10-60_d0.0-0.1": 0.05321233524569066,
        "z10-60_d0.3-0.7": -1.7997896503200193,
        "z120-200_d0.0-0.1": 0.10247759965464488,
        "z120-200_d0.3-0.7": -1.7570525979064509
      },
      "elapsed_s": 2.9
    },
    "6": {
      "valley_depth": 2.5087271936533595,
      "logK_at_gamma": -0.04029578260580941,
      "logK_at_midpoints": 2.46843141104755,
      "mass_frac_pm0.1": 0.6986826134175042,
      "uniform_expectation": 0.09000000000000001,
      "mass_ratio_vs_uniform": 7.7631401490833785,
      "within_bin_meanlogw": {
        "z10-60_d0.0-0.1": -0.10145611105454076,
        "z10-60_d0.3-0.7": -2.4097253102207548,
        "z120-200_d0.0-0.1": 0.029192545882919238,
        "z120-200_d0.3-0.7": -2.314439077156247
      },
      "elapsed_s": 5.1
    },
    "8": {
      "valley_depth": 2.7352201581877043,
      "logK_at_gamma": 0.030554703235580436,
      "logK_at_midpoints": 2.7657748614232847,
      "mass_frac_pm0.1": 0.7251109123178877,
      "uniform_expectation": 0.09000000000000001,
      "mass_ratio_vs_uniform": 8.056787914643197,
      "within_bin_meanlogw": {
        "z10-60_d0.0-0.1": -0.1389960979715335,
        "z10-60_d0.3-0.7": -2.7392603482112916,
        "z120-200_d0.0-0.1": -0.20043183472111312,
        "z120-200_d0.3-0.7": -2.6451890375288283
      },
      "elapsed_s": 7.9
    },
    "10": {
      "valley_depth": 2.8706885758089333,
      "logK_at_gamma": 0.11948603922925684,
      "logK_at_midpoints": 2.9901746150381903,
      "mass_frac_pm0.1": 0.7251715332604941,
      "uniform_expectation": 0.09000000000000001,
      "mass_ratio_vs_uniform": 8.057461480672156,
      "within_bin_meanlogw": {
        "z10-60_d0.0-0.1": -0.07371951844373904,
        "z10-60_d0.3-0.7": -2.974563705268562,
        "z120-200_d0.0-0.1": -0.2233480705431757,
        "z120-200_d0.3-0.7": -2.8788847145178686
      },
      "elapsed_s": 11.4
    },
    "12": {
      "valley_depth": 2.9442229398281423,
      "logK_at_gamma": 0.22834844487190686,
      "logK_at_midpoints": 3.172571384700049,
      "mass_frac_pm0.1": 0.7241062961289328,
      "uniform_expectation": 0.09000000000000001,
      "mass_ratio_vs_uniform": 8.045625512543698,
      "within_bin_meanlogw": {
        "z10-60_d0.0-0.1": -0.1831905054381875,
        "z10-60_d0.3-0.7": -3.1605455546413452,
        "z120-200_d0.0-0.1": -0.35321115246295404,
        "z120-200_d0.3-0.7": -3.0663074224107776
      },
      "elapsed_s": 15.5
    },
    "V4_saturation_fit": {
      "Delta_inf": 3.3338697242432738,
      "c": 4.760242352939846,
      "max_resid": 0.03176880509994007
    },
    "valley_depths": {
      "4.0": 2.1593140478568413,
      "6.0": 2.5087271936533595,
      "8.0": 2.7352201581877043,
      "10.0": 2.8706885758089333,
      "12.0": 2.9442229398281423
    }
  },
  "elapsed_seconds": 59.7,
  "timestamp_utc": "2026-08-19T17:37:47.138364+00:00"
}

Source code

Python script (click to expand)
"""E-022b — task 2.10 analysis stage: reproducing-kernel valley structure
and gamma-mass concentration (post-hoc analysis of E-022).

E-022 found the coarse weak metric flat (O3) but a persistent mass
elevation near the true zeros. This script resolves the mechanism:

  K_a(z,z) := Re(b_z^H v), v the bordered (L^2_0) Galerkin solution of
  T_a v = e^{-izx} — the diagonal of the model-space reproducing kernel.

Measurements (a in {4,6,8,10,12}, theta=pi):
  V1. valley depth: Delta(a) = mean log K at gamma-gap midpoints minus
      mean log K at gammas, z-grid step 0.05 in [14,60).
  V2. mass concentration: fraction of the E-022 spectral mass within
      +/-0.1 of a true zero (vs uniform-lattice expectation).
  V3. artifact control: mean log w vs distance-to-nearest-gamma WITHIN
      z-bins (controls the gamma-density/weight-trend confound that
      naive O5 fails — shifted-gamma null test showed the raw O5
      elevation is mostly distributional).
  V4. saturation model: Delta(a) ~ Delta_inf - c/a fit.

Outputs: research/numerics/data/E-022b-valley.csv (+ .json)
"""
import importlib.util
import json
import sys
import time
from datetime import datetime, timezone
from pathlib import Path

import mpmath as mp
import numpy as np
import scipy.linalg

REPO = Path(__file__).resolve().parents[3]
DATA = REPO / "research" / "numerics" / "data"
CSV = DATA / "E-022b-valley.csv"
JSON = DATA / "E-022b-valley.json"

spec = importlib.util.spec_from_file_location(
    "E16", Path(__file__).with_name("E-016-herglotz-fine-structure.py"))
E16 = importlib.util.module_from_spec(spec)
spec.loader.exec_module(E16)                     # runs the e^20 sieve
sys.path.insert(0, str(Path(__file__).parent))
from prime_backend_v2 import PrimeBackendV2       # noqa: E402

H = E16.H_MAIN
LAM = E16.LAM_SHIFT
A_LIST = (4.0, 6.0, 8.0, 10.0, 12.0)
XN = E16.XN


def collect_t_points(a, h):
    n_elem = int(round(2 * a / h))
    pts = []

    def add_quad(lo, hi, peak):
        n_lo = int(np.ceil(np.exp(lo)))
        n_hi = int(np.floor(np.exp(hi)))
        if n_hi - n_lo > 64:
            for aa, bb in ((lo, peak), (peak, hi)):
                if bb - aa > 0:
                    mid, half = 0.5 * (aa + bb), 0.5 * (bb - aa)
                    pts.extend(mid + half * XN)
            return
        segs = sorted({lo, peak, hi} |
                      {float(np.log(n))
                       for n in range(max(n_lo, 2), n_hi + 1)
                       if lo < np.log(n) < hi})
        for p0, p1 in zip(segs, segs[1:]):
            if p1 - p0 > 0:
                mid, half = 0.5 * (p0 + p1), 0.5 * (p1 - p0)
                pts.extend(mid + half * XN)

    for k in range(n_elem):
        if k == 0:
            add_quad(0.0, h, 0.0)
        else:
            add_quad((k - 1) * h, (k + 1) * h, k * h)
    return np.array(pts)


def make_K1(a):
    x, h, Q, M, _b = E16.build(a, H)
    n = Q.shape[0]
    mc = np.zeros(n)
    mc[0] = 2 * h / 3
    mc[1] = h / 6
    tc = Q[:, 0] - LAM * mc
    u1 = scipy.linalg.solve_toeplitz((tc, tc), np.ones(n))
    s1 = u1.sum()

    def K1(z):
        bz = E16.hat_FT(np.array([z]), h)[0] * np.exp(-1j * z * x)
        u0 = scipy.linalg.solve_toeplitz((tc, tc), bz)
        v = u0 - (u0.sum() / s1) * u1
        return float(np.real(np.conj(bz) @ v))

    return K1


def main() -> int:
    if JSON.exists() and "--force" not in sys.argv:
        print(f"cached: {JSON} (use --force to recompute)")
        return 0
    t0 = time.time()

    tq = np.concatenate([collect_t_points(a, H) for a in A_LIST])
    be = PrimeBackendV2(tq)
    be.load_cache(DATA / "E-022-backend-cache.npz")
    E16._BUILD.clear()
    E16.prime_sum_vec = be.prime_sum

    mp.mp.dps = 30
    gam_all = np.array([float(mp.zetazero(k).imag)
                        for k in range(1, 201)])
    gam = gam_all[gam_all <= 280]

    # E-022 weights
    import csv as csvmod
    data = {}
    with open(DATA / "E-022-spectral-measure.csv") as f:
        for r in csvmod.DictReader(f):
            data.setdefault(float(r["a"]), []).append(
                (float(r["z_k"]), float(r["w_k"])))

    zgrid = np.arange(14.0, 60.0, 0.05)
    gsel = gam_all[(gam_all >= 14) & (gam_all < 60)]
    mids = (gsel[:-1] + gsel[1:]) / 2
    idxg = np.round((gsel - 14) / 0.05).astype(int)
    idxm = np.round((mids - 14) / 0.05).astype(int)

    per_a = {}
    grid_rows = []
    for a in A_LIST:
        ta = time.time()
        K1 = make_K1(a)
        lg = np.array([np.log(K1(z)) for z in zgrid])
        dip = float(lg[idxm].mean() - lg[idxg].mean())
        # mass fraction within +-0.1 of gamma (full window to 280)
        z = np.array([p[0] for p in data[a]])
        w = np.array([p[1] for p in data[a]])
        m = z <= 280
        zm, wm = z[m], w[m]
        idx = np.clip(np.searchsorted(gam, zm), 1, len(gam) - 1)
        d = np.minimum(np.abs(zm - gam[idx - 1]), np.abs(zm - gam[idx]))
        frac = float(wm[d <= 0.1].sum() / wm.sum())
        unif = float(0.2 * len(gam) / 280.0)
        # V3: within-z-bin mean log w by distance bin
        lw = np.log(wm)
        bins = {}
        for lo, hi in ((10, 60), (120, 200)):
            sel = (zm >= lo) & (zm < hi)
            for blo, bhi in ((0.0, 0.1), (0.3, 0.7)):
                s2 = sel & (d >= blo) & (d < bhi)
                if s2.sum() > 3:
                    bins[f"z{lo}-{hi}_d{blo}-{bhi}"] = float(lw[s2].mean())
        per_a[f"{a:g}"] = {
            "valley_depth": dip,
            "logK_at_gamma": float(lg[idxg].mean()),
            "logK_at_midpoints": float(lg[idxm].mean()),
            "mass_frac_pm0.1": frac,
            "uniform_expectation": unif,
            "mass_ratio_vs_uniform": frac / unif,
            "within_bin_meanlogw": bins,
            "elapsed_s": round(time.time() - ta, 1),
        }
        print(f"a={a:g}: dip={dip:.4f}, massfrac={frac:.4f} "
              f"({per_a[f'{a:g}']['elapsed_s']}s)", flush=True)
        for zz, ll in zip(zgrid, lg):
            grid_rows.append((a, zz, ll))

    # V4: saturation fit Delta(a) = Dinf - c/a
    av = np.array(A_LIST)
    dv = np.array([per_a[f"{a:g}"]["valley_depth"] for a in A_LIST])
    Afit = np.vstack([np.ones_like(av), -1.0 / av]).T
    Dinf, c = np.linalg.lstsq(Afit, dv, rcond=None)[0]
    resid = dv - (Dinf - c / av)
    print(f"V4: Delta_inf = {Dinf:.3f}, c = {c:.3f}, "
          f"max fit resid {np.abs(resid).max():.4f}", flush=True)

    checks = {
        "V1_valleys_at_gamma": bool(np.all(dv > 1.5)),
        "V2_mass_concentrated": bool(np.all(
            [per_a[f"{a:g}"]["mass_frac_pm0.1"] > 0.5 for a in A_LIST])),
        "V4_fit_quality": bool(np.abs(resid).max() < 0.1),
    }

    with open(CSV, "w", newline="") as f:
        wcsv = csvmod.writer(f)
        wcsv.writerow(["a", "z", "logK"])
        for a, zz, ll in grid_rows:
            wcsv.writerow([f"{a:g}", f"{zz:.3f}", f"{ll:.6f}"])

    meta = {
        "experiment": "E-022b",
        "task": "2.10 analysis: K-diagonal valleys + mass concentration",
        "script": "research/numerics/scripts/E-022b-valley-analysis.py",
        "checks": checks,
        "key_values": {**per_a,
                       "V4_saturation_fit": {"Delta_inf": float(Dinf),
                                             "c": float(c),
                                             "max_resid": float(
                                                 np.abs(resid).max())},
                       "valley_depths": dict(zip([str(a) for a in av],
                                                 dv.tolist()))},
        "elapsed_seconds": round(time.time() - t0, 1),
        "timestamp_utc": datetime.now(timezone.utc).isoformat(),
    }
    JSON.write_text(json.dumps(meta, indent=2))
    print(f"wrote {CSV.name}, {JSON.name}; elapsed "
          f"{meta['elapsed_seconds']}s", flush=True)
    return 0 if all(checks.values()) else 1


if __name__ == "__main__":
    sys.exit(main())