Review index · Download raw source
reference/analytic/deadtime.py
1from pathlib import Path2import csv,datetime,json,math,sys3sys.path.insert(0,r'D:/Photometer_research_20261022/research/cloud_transport/private_readers')4from scipy.optimize import brentq56p=Path(r'D:/Photometer_research_20261022/revision_20261022_r4/analysis/analytic/deadtime')7p.mkdir(exist_ok=True)8tau=17e-9;rows=[]9for background in [50.,1e6,1e8]:10 for peak_signal in [1e6,5e6,5e7,1e8,1e9,3e9,1e10]:11 x=peak_signal*tau/(1+background*tau)12 frac10=.1/(1+.9*x);frac90=.9/(1+.1*x)13 shrink=(frac90-frac10)/.814 def counter(rate):return rate/(1+rate*tau)15 mb=counter(background);mp=counter(background+peak_signal)16 def normalized_response(f):return (counter(background+peak_signal*f)-mb)/(mp-mb)17 numeric10=brentq(lambda f:normalized_response(f)-.1,0,1)18 numeric90=brentq(lambda f:normalized_response(f)-.9,0,1)19 assert abs(numeric10-frac10)<1e-10 and abs(numeric90-frac90)<1e-1020 for input_rise in [30.,80.,200.,300.]:21 rows.append(dict(assumed_nonparalyzable_deadtime_s=tau,background_true_cps=background,22 peak_true_signal_cps=peak_signal,peak_total_true_cps=background+peak_signal,23 peak_mean_registered_cps=mp,baseline_mean_registered_cps=mb,24 peak_total_fraction_lost=1-mp/(background+peak_signal),effective_signal_occupancy=x,25 input_linear_10_90_rise_us=input_rise,26 output_uncorrected_10_90_rise_us=input_rise*shrink,27 output_over_input_rise=shrink,source_fraction_at_output10pct=frac10,source_fraction_at_output90pct=frac90,28 inverse_mean_rate_slope_at_peak=(1+(background+peak_signal)*tau)**2,29 approximation='Quasi-staticmeanresponseofnonparalyzablecounter; noeventwaveformormisclassificationprobability'))30with (p/'conditional_rise_bias.csv').open('w',newline='',encoding='utf-8') as f:31 w=csv.DictWriter(f,fieldnames=list(rows[0]));w.writeheader();w.writerows(rows)32report={'recorded_utc':datetime.datetime.now(datetime.timezone.utc).isoformat(),33 'status':'OWN_CONDITIONAL_MEAN_RESPONSE_DIAGNOSTIC_NOT_MEASURED_FLIGHT_BIAS',34 'questions':['A2','C7','C8','C9','E16','G21','G22'],35 'primary_context':'Chanrionetal2019MMIA DOI10.1007/s11214-019-0593-y section6.3 photon-countconversion;17ns337deadtimeisafrozenstudyassumption/actualCDFparameter. Exactreceiverarchitectureanddeadtime mustbeverified.',36 'own_derivation':{37 'true_rate':'r(t)=b+S*f(t), flinear0to1overrampT',38 'registered_mean_rate':'m(r)=r/(1+r*tau), strictlyNONPARALYZABLEmodel',39 'baseline_subtracted_fraction_of_registered_peak':'y=f*(1+x)/(1+x*f), x=S*tau/(1+b*tau)',40 'inverse_fraction':'f(y)=y/[1+x*(1-y)]',41 '10_90_ratio':'[.9/(1+.1*x)-.1/(1+.9*x)]/.8',42 '10_90_ratio_simplified':'(1+x)/(1+x+.09*x*x); symmetric10–90compressionbeginsatsecondorderforsmallx',43 'generic_intrinsic_waveform':'t_y=f_inverse(y/[1+x*(1-y)]); simplifiedcompressionaboveisspecifictolinearramp',44 'mean_correction':'r=m/(1-m*tau), dr/dm=1/(1-m*tau)^2',45 'approximation':'rchangeson30–300us scales muchlongerthan17ns; quasistaticexpectationonly'},46 'scope_limits':['OnlyRAWuncorrectedmeanwaveformshape; publishedcorrectedMMIAwaveformscannotbeaccusedofthisbiasfromthisdiagnostic','Noactualsourcebrightnessdistributionordetectorselected','Noafterpulsing,paralyzableholdoff,discriminatorwalk,gainsag,baselineestimation,electronics/samplingorcountlikelihood','StationaryPoissonarrivalmeanresponseappliedquasi-statically; notexactstochasticwaveform','Mathematicalinversionrecoversthemeanonlyforavalidknownmodel; doesnotrestorelostphotons orPoissonstatistics','Binwiseinverseisnonlinear: expectedinverseofmeasuredcountisnotinverseofexpectedcount','A200usinputcangiveraw~tens-usapparentrisewhenstronglysaturated; thisisnot evidencefainteventsactuallydoso','Simplyenlargingapertureatfixedthroughputraisesmeanrate; gainchangesaloneare notassumedtocorrectdeadtime'],47 'validation':{'analyticversusindependentnumericalamplituderoots':21,'rows':len(rows)},48 'examples':[r for r in rows if r['background_true_cps']==50 and r['input_linear_10_90_rise_us']==200]}49(p/'derivation_and_qualification.json').write_text(json.dumps(report,indent=2),encoding='utf-8')50print(json.dumps({'rows':len(rows),'examples':report['examples']},indent=2))51