[docs]classSvgFlowable(Flowable):"""Convert byte streasm containing SVG into a Reportlab Flowable."""def__init__(self,svg:BytesIO)->None:"""Convert SVG to RML drawing on initializtion."""svg.seek(0)
[docs]defdraw(self)->None:"""Render the chart."""renderPDF.draw(self.drawing,self.canv,0,0)
[docs]classReporter():def__init__(self,filepath,pagesize='A4')->None:# Build the pdfifpagesize=='A4':PAGESIZE=pagesizes.portrait(pagesizes.A4)elifpagesize=='Letter':PAGESIZE=pagesizes.portrait(pagesizes.LETTER)else:raiseValueError("Only pagesizes of 'A4' or 'Letter' are supported")
[docs]def_build(self):# Convert ordered dict to list of values and then flattenflat_list=[]forkeyinself.story:flat_list+=self.story[key]self.pdf.build(flat_list)
[docs]defadd_figure(self,key,figure,title=None):# Add a matplotlib figure to the reportlab documentiftitleisnotNone:self.story[key].append(Paragraph(title,styles['Heading4']))imgdata=BytesIO()# Resize figure whilst preservaing aspect ratiowidth=figure.get_figwidth()height=figure.get_figheight()aspect=height/widthNew_width=5figure.set_figwidth(New_width)figure.set_figheight(New_width*aspect)figure.tight_layout()figure.savefig(imgdata,format='svg')imgdata.seek(0)# rewind the dataself.story[key].append(SvgFlowable(imgdata))
[docs]defadd_table(self,key,lists):"""Generates a table as a reportlab flowable from a list of lists """t=Table(lists)t.setStyle(TableStyle([('ALIGN',(1,1),(-2,-2),'RIGHT'),]))self.story[key].append(t)
[docs]defcombo_figure(EDFS,respro,pulses:dict,relaxation:list,init_deer,long_deer,title=None):""" Creates a 2x2 summary figure. - The top left plot is the EDFS and resonator profile, overlapped with the optimised pulses. - The top right plot is the relaxation data and fits. - The bottom left plot is the initial DEER data and fits. - The bottom right plot is the final DEER data and fits. Parameters ---------- EDFS: ad.FieldSweepAnalysis The Echo-Detected Field Sweep analysis. respro: ad.ResonatorProfileAnalysis The resonator profile analysis pulses: dict A dictionary containing the optimised pulses. relaxation: list A list containing the relaxation data and fits. init_deer: deerlab.FitResult The initial DEER data and fits. long_deer: deerlab.FitResult The final DEER data and fits. title: str, optional The title of the figure, by default None """figure=plt.figure(figsize=(10,10),constrained_layout=True)figs=figure.subfigures(2,2,height_ratios=(4,6),width_ratios=(1,1),wspace=.12)iftitleisnotNone:figure.suptitle(title,size=20)figs[0,0].suptitle('a. EDFS',size=15)plot_overlap(EDFS,pulses['pump_pulse'],pulses['exc_pulse'],pulses['ref_pulse'],respro=respro,fig=figs[0,0]);figs[0,0].axes[0].set_xlim(-300,100)figs[0,1].suptitle('b. Relaxation',size=15)plot_1Drelax(*relaxation,fig=figs[0,1])figs[1,0].suptitle('c. Intial DEER',size=15)DEERanalysis_plot_pub(init_deer[0],ROI=init_deer[0].ROI,fig=figs[1,0]);figs[1,1].suptitle('d. Final DEER',size=15)DEERanalysis_plot_pub(long_deer,fig=figs[1,1]);returnfigure