from pathlib import Path
import json,csv,math
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
root=Path(__file__).resolve().parent
rows=[(0.0,1.86),(2.7,1.44),(6.8,1.13),(13.7,0.80)]
with (root/'cloud-variability-2025.csv').open('w',newline='',encoding='utf-8') as f:
 w=csv.writer(f);w.writerow(['modeled_cloud_cover_setting_percent','reported_simulated_reconstruction_snr']);w.writerows(rows)
(root/'cloud-variability-2025-methods.json').write_text(json.dumps({
 'source':'Viktor T. Toth (2025), Research in Astronomy and Astrophysics 25(6), 065007',
 'doi':'10.1088/1674-4527/add3a3','open_manuscript':'https://arxiv.org/html/2504.18630',
 'locator':'Table 1; §§4 and 6. The RAA paper page identifies the peer-reviewed publication.',
 'data_status':'Values transcribed from a published simulation table, not observations or independently repeated simulations.',
 'source_values':rows,
 'scenario':['Earth-like source topography with rotation/orbit and changing illumination','Heuristic multilayer Perlin-noise clouds form, dissipate and move linearly; the cloud model is not a climate model.','The four percentages are internal cloud-control settings, not measured cloud fractions.','The cloud model is integrated with the paper’s SGL image-recovery simulation. It directly samples the projected image plane without an explicit telescope, detector or sampling-instrument model.','A 1-degree source-map grid is used as the closest proxy for aperture size; about 200 simulated measurement epochs, 2.5 hours apart, have about 120 projected-plane samples each across 500 hours (about 24,000 total). Some samples fall on unilluminated locations.','About 5,700 reconstructed cells; pixels south of 45 degrees S are excluded for the chosen 45 degrees N vantage point.'],
 'limits':['Cloud model is not a climate model or realistic Earth cloud climatology.','The 1-degree source-grid proxy is not a modeled optical aperture, telescope, detector or instrument-sampling response.','Only four internal cloud-cover settings are reported, and no uncertainty bars are supplied for this comparison.','The results identify a surface-map reconstruction risk; they do not test or invalidate gravitational lensing physics and do not settle a complete mission feasibility study.','The line simply connects four reported cases; it is not a continuous response law or interpolation model.'],
 'plot':'Original plotting of the four Table 1 simulated SNR values. No source figure pixels were copied.'
},ensure_ascii=False,indent=2)+'\n',encoding='utf-8')
plt.rcParams.update({'font.size':15,'text.color':'#edf4ff','axes.labelcolor':'#edf4ff','xtick.color':'#edf4ff','ytick.color':'#edf4ff','axes.edgecolor':'#9db4d9','svg.fonttype':'none'})
fig,ax=plt.subplots(figsize=(9.6,5.4),dpi=130,facecolor='#07152b');ax.set_facecolor('#07152b')
x=[a for a,b in rows];y=[b for a,b in rows]
ax.plot(x,y,color='#ff5aa9',linewidth=2.8,marker='o',markersize=10,markerfacecolor='#07152b',markeredgewidth=3,markeredgecolor='#ff83c3')
for a,b in rows: ax.annotate(f'{b:.2f}',(a,b),xytext=(0,12),textcoords='offset points',ha='center',color='#fff0f7',fontsize=14)
ax.set(xlim=(-.7,14.5),ylim=(0,2.15),xlabel='Modeled cloud-cover setting (%)',ylabel='Simulated recovered-image SNR')
ax.set_xticks(x);ax.set_yticks([0,.5,1,1.5,2]);ax.grid(axis='y',alpha=.22,color='#b8c9e8')
fig.suptitle('Greater modeled cloud cover, lower recovered SNR',fontsize=20,x=.53,y=.98)
fig.text(.13,.90,'Toth (2025), Table 1 · SGL image-recovery simulation',fontsize=12,color='#bfd5f5')
fig.text(.13,.02,'Four settings only · projected-plane samples, no telescope/detector model · no uncertainty bars',fontsize=10.5,color='#f7c566')
fig.subplots_adjust(left=.16,right=.97,bottom=.20,top=.80)
svg=root/'cloud-variability-2025.svg';fig.savefig(svg,facecolor=fig.get_facecolor());fig.savefig(root/'cloud-variability-2025.png',facecolor=fig.get_facecolor());plt.close(fig)
svg.write_text('\n'.join(z.rstrip() for z in svg.read_text(encoding='utf-8').splitlines())+'\n',encoding='utf-8')
print('generated',rows)
