from pathlib import Path
import csv, json
base=Path(__file__).resolve().parent
points=[
(12,85,1.99,1.86,75.34,3035,.602),(11,83,1.94,1.82,72.55,3125,.610),(11,83,1.96,1.83,72.63,3131,.609),
(10,77,1.84,1.72,69.54,3000,.594),(10,76,1.82,1.70,67.21,3109,.602),(10,75,1.79,1.68,66.81,3087,.601),
(10,74,1.77,1.66,66.11,3054,.595),(10,73,1.75,1.65,65.64,3035,.594),(10,72,1.73,1.63,65.15,3012,.592),
(9,69,1.67,1.57,62.27,3070,.597),(6,48,1.29,1.22,47.43,3006,.573),(6,48,1.29,1.22,47.39,3004,.571),
(3,27,.89,.84,31.70,2770,.511),(0,6,.50,.48,20.77,1961,.418)]
fields=['NSTAR_throttle_level','mission_throttle_level','ppu_input_kW','engine_input_kW','navigation_derived_thrust_mN','specific_impulse_s','total_efficiency_fraction']
with (base/'ds1-nstar-flight-points.csv').open('w',newline='',encoding='utf-8') as f:
 w=csv.writer(f);w.writerow(fields);w.writerows(points)
methods={"title":"NSTAR DS1 flight points transcribed from JPL Publication 00-10 Table 12","source_url":"https://pdssbn.astro.umd.edu/holdings/ds1-c-micas-3-rdr-visccd-borrelly-v1.0/document/doc_Apr04/int_reports/IPS_Integrated_Report.pdf","source_sha256":"C160FE9CA4D81174B7D51FC6FDDC61D368C7AA3176D0B51F1D2891E8003BA77F","locator":"PDF page 40 / printed page 33, Table 12","plot":{"x":"PPU input power (kW)","y":"navigation-derived in-flight thrust estimate (mN)","marks":"14 points, preserving repeated throttle levels; no fitted curve or extrapolation","uncertainty":"No bars plotted. Report §2.6.2.4 estimates <0.5 mN uncertainty in navigation-derived thrust; this is not described as a 1-sigma or 95% interval and does not include calculated-thrust model error."},"boundary":"PPU input is not the same quantity as engine input; thrust is inferred from Doppler/radio tracking and a spacecraft-mass-versus-time model, not measured by an onboard load cell. Table 12 does not label each row by mission phase or operating mode.","limitations":["14 observations span 13 distinct throttle-level pairs; repeated levels are shown as separate points.","No curve fit, interpolation, or extrapolation is supplied.","At mission throttle level 83 (about 1.82 kW engine input), the report notes measured thrust up to 1.6 mN below the calculated value; figure error bars exclude calculated-thrust model uncertainty.","This was flight use of solar electric propulsion after launch, not launch from Earth."]}
(base/'ds1-nstar-flight-points-methods.json').write_text(json.dumps(methods,indent=2)+'\n',encoding='utf-8')
def svg(mobile=False):
 W,H=(760,520) if mobile else (1060,640); left,right=(92,W-35); top,bottom=(52,H-96); xmin,xmax=.4,2.1; ymin,ymax=15,80
 X=lambda v:left+(v-xmin)/(xmax-xmin)*(right-left)
 Y=lambda v:bottom-(v-ymin)/(ymax-ymin)*(bottom-top)
 parts=[f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {W} {H}" role="img" aria-labelledby="title desc"><title id="title">Deep Space 1 NSTAR flight points</title><desc id="desc">Scatter plot of fourteen navigation-derived in-flight thrust estimates against PPU input power from the flight-performance table. Repeated throttle points are preserved. No fitted curve; these are not load-cell measurements.</desc><rect width="100%" height="100%" fill="#08172d"/><text x="{left}" y="30" fill="#f2f6ff" font-size="{26 if mobile else 19}" font-weight="700">In-space NSTAR observations · 14 operating points</text>']
 for v in ([20,40,60,80] if mobile else [20,30,40,50,60,70,80]):
  y=Y(v);parts.append(f'<path d="M{left} {y:.1f}H{right}" stroke="#304560"/><text x="{left-12}" y="{y+5:.1f}" text-anchor="end" fill="#c9d7eb" font-size="{22 if mobile else 14}">{v}</text>')
 for v in ([.5,1,1.5,2] if mobile else [.5,.75,1,1.25,1.5,1.75,2]):
  x=X(v);parts.append(f'<path d="M{x:.1f} {top}V{bottom}" stroke="#233a55"/><text x="{x:.1f}" y="{bottom+25}" text-anchor="middle" fill="#c9d7eb" font-size="{20 if mobile else 13}">{v:g}</text>')
 parts += [f'<path d="M{left} {top}V{bottom}H{right}" fill="none" stroke="#d7e7ff" stroke-width="2"/>',f'<text x="{(left+right)/2}" y="{H-28}" text-anchor="middle" fill="#f2f6ff" font-size="{23 if mobile else 16}">PPU input power (kW)</text>',f'<text x="24" y="{(top+bottom)/2}" transform="rotate(-90 24 {(top+bottom)/2})" text-anchor="middle" fill="#f2f6ff" font-size="{23 if mobile else 16}">Thrust estimate (mN)</text>']
 for i,p in enumerate(points):
  x,y=X(p[2]),Y(p[4]); title=f'NSTAR level {p[0]}, mission level {p[1]}; PPU {p[2]:.2f} kW; engine {p[3]:.2f} kW; thrust estimate {p[4]:.2f} mN; Isp {p[5]} s'
  parts.append(f'<circle cx="{x:.1f}" cy="{y:.1f}" r="{9 if mobile else 7}" fill="#5fd3ff" stroke="#ffffff" stroke-width="1.5"><title>{title}</title></circle>')
 parts.append(f'<text x="{left}" y="{H-7}" fill="#ffd6a5" font-size="{19 if mobile else 13}">Flight-derived thrust estimate; report bound &lt;0.5 mN, not a statistical confidence interval. No curve fit.</text></svg>')
 return '\n'.join(parts)+'\n'
(base/'ds1-nstar-flight-points.svg').write_text(svg(),encoding='utf-8')
(base/'ds1-nstar-flight-points-mobile.svg').write_text(svg(True),encoding='utf-8')
