def shift_report(inFID, outFID, inHdr, outHdr, ppmlim=(0.2, 4.2), html=None, function='shift'): """ Generate report """ import plotly.graph_objects as go from plotly.subplots import make_subplots from fsl_mrs.utils.preproc.reporting import plotStyles, plotAxesStyle plotIn = MRS(FID=inFID, header=inHdr) plotOut = MRS(FID=outFID, header=outHdr) # Fetch line styles lines, colors, _ = plotStyles() # Make a new figure fig = make_subplots(rows=1, cols=2, subplot_titles=['Spectra', 'FID']) # Add lines to figure trace1 = go.Scatter(x=plotIn.getAxes(ppmlim=ppmlim), y=np.real(plotIn.getSpectrum(ppmlim=ppmlim)), mode='lines', name='Original', line=lines['in']) trace2 = go.Scatter(x=plotOut.getAxes(ppmlim=ppmlim), y=np.real(plotOut.getSpectrum(ppmlim=ppmlim)), mode='lines', name='Shifted', line=lines['out']) fig.add_trace(trace1, row=1, col=1) fig.add_trace(trace2, row=1, col=1) # Add lines to figure trace3 = go.Scatter(x=plotIn.getAxes(axis='time'), y=np.real(plotIn.FID), mode='lines', name='Original', line=lines['emph']) trace4 = go.Scatter(x=plotOut.getAxes(axis='time'), y=np.real(plotOut.FID), mode='lines', name='Shifted', line=lines['diff']) fig.add_trace(trace3, row=1, col=2) fig.add_trace(trace4, row=1, col=2) # Axes layout plotAxesStyle(fig, ppmlim, title='Shift summary') fig.layout.xaxis2.update(title_text='Time (s)') fig.layout.yaxis2.update(zeroline=True, zerolinewidth=1, zerolinecolor='Gray', showgrid=False, showticklabels=False) if html is not None: from plotly.offline import plot from fsl_mrs.utils.preproc.reporting import figgroup, singleReport from datetime import datetime import os.path as op if op.isdir(html): filename = 'report_' + datetime.now().strftime( "%Y%m%d_%H%M%S%f")[:-3] + '.html' htmlfile = op.join(html, filename) elif op.isdir(op.dirname(html)) and op.splitext(html)[1] == '.html': htmlfile = html else: raise ValueError('Report html path must be file or directory. ') operation, function, description = reportStrings(function) opName = operation timestr = datetime.now().strftime("%H:%M:%S") datestr = datetime.now().strftime("%d/%m/%Y") headerinfo = f'Report for fsl_mrs.utils.preproc.shifting.{function}.\n'\ + f'Generated at {timestr} on {datestr}.' # Figures div = plot(fig, output_type='div', include_plotlyjs='cdn') figurelist = [ figgroup(fig=div, name='', foretext=f'{description}', afttext=f'') ] singleReport(htmlfile, opName, headerinfo, figurelist) return fig else: return fig
def combine_FIDs_report(inFIDs, outFID, hdr, ncha=2, ppmlim=(0.0, 6.0), method='not specified', html=None): """ Take list of FIDs that are passed to combine and output If uncombined data it will display ncha channels (default 2). """ from fsl_mrs.core import MRS import plotly.graph_objects as go from fsl_mrs.utils.preproc.reporting import plotStyles, plotAxesStyle from matplotlib.pyplot import cm toMRSobj = lambda fid: MRS(FID=fid, header=hdr) # Assemble data to plot toPlotIn = [] colourVecIn = [] legendIn = [] if isinstance(inFIDs, list): for idx, fid in enumerate(inFIDs): if inFIDs[0].ndim > 1: toPlotIn.extend([toMRSobj(f) for f in fid[:, :ncha].T]) colourVecIn.extend([idx / len(inFIDs)] * ncha) legendIn.extend( [f'FID #{idx}: CHA #{jdx}' for jdx in range(ncha)]) else: toPlotIn.append(toMRSobj(fid)) colourVecIn.append(idx / len(inFIDs)) legendIn.append(f'FID #{idx}') elif inFIDs.ndim > 1: toPlotIn.extend([toMRSobj(f) for f in inFIDs[:, :ncha].T]) colourVecIn.extend([float(jdx) / ncha for jdx in range(ncha)]) legendIn.extend([f'FID #0: CHA #{jdx}' for jdx in range(ncha)]) toPlotOut = [] legendOut = [] if outFID.ndim > 1: toPlotOut.extend([toMRSobj(f) for f in outFID[:, :ncha].T]) legendOut.extend([f'Combined: CHA #{jdx}' for jdx in range(ncha)]) else: toPlotOut.append(toMRSobj(outFID)) legendOut.append('Combined') def addline(fig, mrs, lim, name, linestyle): trace = go.Scatter(x=mrs.getAxes(ppmlim=lim), y=np.real(mrs.getSpectrum(ppmlim=lim)), mode='lines', name=name, line=linestyle) return fig.add_trace(trace) lines, colors, _ = plotStyles() colors = cm.Spectral(np.array(colourVecIn).ravel()) fig = go.Figure() for idx, fid in enumerate(toPlotIn): cval = np.round(255 * colors[idx, :]) linetmp = {'color': f'rgb({cval[0]},{cval[1]},{cval[2]})', 'width': 1} fig = addline(fig, fid, ppmlim, legendIn[idx], linetmp) for idx, fid in enumerate(toPlotOut): fig = addline(fig, fid, ppmlim, legendOut[idx], lines['blk']) plotAxesStyle(fig, ppmlim, 'Combined') # Generate report if html is not None: from plotly.offline import plot from fsl_mrs.utils.preproc.reporting import figgroup, singleReport from datetime import datetime import os.path as op if op.isdir(html): filename = 'report_' + datetime.now().strftime( "%Y%m%d_%H%M%S%f")[:-3] + '.html' htmlfile = op.join(html, filename) elif op.isdir(op.dirname(html)) and op.splitext(html)[1] == '.html': htmlfile = html else: raise ValueError('Report html path must be file or directory. ') opName = 'Combination' timestr = datetime.now().strftime("%H:%M:%S") datestr = datetime.now().strftime("%d/%m/%Y") headerinfo = 'Report for fsl_mrs.utils.preproc.combine.combine_FIDs.\n'\ + f'Generated at {timestr} on {datestr}.' # Figures div = plot(fig, output_type='div', include_plotlyjs='cdn') figurelist = [ figgroup(fig=div, name='', foretext=f'Combination of spectra. Method = {method}', afttext=f'') ] singleReport(htmlfile, opName, headerinfo, figurelist) return fig else: return fig
def hlsvd_report(inFID, outFID, hdr, limits, limitUnits='ppm', plotlim=(0.2, 6), html=None): """ Generate hlsvd report """ # from matplotlib import pyplot as plt from fsl_mrs.core import MRS import plotly.graph_objects as go from fsl_mrs.utils.preproc.reporting import plotStyles, plotAxesStyle # Turn input FIDs into mrs objects def toMRSobj(fid): return MRS(FID=fid, header=hdr) plotIn = toMRSobj(inFID) plotOut = toMRSobj(outFID) plotDiff = toMRSobj(outFID - inFID) if limitUnits.lower() == 'ppm': limits = np.array(limits) + H2O_PPM_TO_TMS elif limitUnits.lower() == 'ppm+shift': pass elif limitUnits.lower() == 'hz': limits = (np.array(limits)/(plotIn.centralFrequency/1E6)) + \ H2O_PPM_TO_TMS else: raise ValueError('limitUnits should be one of: ppm, ppm+shift or hz.') # Fetch line styles lines, colors, _ = plotStyles() # Make a new figure fig = go.Figure() # Add lines to figure def addline(fig, mrs, lim, name, linestyle): trace = go.Scatter(x=mrs.getAxes(ppmlim=lim), y=np.real(mrs.getSpectrum(ppmlim=lim)), mode='lines', name=name, line=linestyle) return fig.add_trace(trace) fig = addline(fig, plotIn, plotlim, 'Uncorrected', lines['in']) fig = addline(fig, plotIn, limits, 'Limits', lines['emph']) fig = addline(fig, plotOut, plotlim, 'Corrected', lines['out']) fig = addline(fig, plotDiff, plotlim, 'Difference', lines['diff']) # Axes layout plotAxesStyle(fig, plotlim, title='HLSVD summary') # Axes if html is not None: from plotly.offline import plot from fsl_mrs.utils.preproc.reporting import figgroup, singleReport from datetime import datetime import os.path as op if op.isdir(html): filename = 'report_' + \ datetime.now().strftime("%Y%m%d_%H%M%S%f")[:-3]+'.html' htmlfile = op.join(html, filename) elif op.isdir(op.dirname(html)) and op.splitext(html)[1] == '.html': htmlfile = html else: raise ValueError('Report html path must be file or directory. ') opName = 'HLSVD' timestr = datetime.now().strftime("%H:%M:%S") datestr = datetime.now().strftime("%d/%m/%Y") headerinfo = 'Report for fsl_mrs.utils.preproc.remove.HLSVD.\n' + \ f'Generated at {timestr} on {datestr}.' # Figures div = plot(fig, output_type='div', include_plotlyjs='cdn') figurelist = [ figgroup(fig=div, name='', foretext='HLSVD removal of peaks in the range' f' {limits[0]:0.1f} to' f' {limits[1]:0.1f} ppm.', afttext='') ] singleReport(htmlfile, opName, headerinfo, figurelist) return fig else: return fig
def apodize_report(inFID, outFID, hdr, plotlim=(0.2, 6), html=None): """ Generate report """ # from matplotlib import pyplot as plt from fsl_mrs.core import MRS import plotly.graph_objects as go from fsl_mrs.utils.preproc.reporting import plotStyles, plotAxesStyle # Turn input FIDs into mrs objects toMRSobj = lambda fid: MRS(FID=fid, header=hdr) plotIn = toMRSobj(inFID) plotOut = toMRSobj(outFID) # Fetch line styles lines, colors, _ = plotStyles() # Make a new figure fig = go.Figure() # Add lines to figure def addline(fig, mrs, lim, name, linestyle): trace = go.Scatter(x=mrs.getAxes(ppmlim=lim), y=np.real(mrs.getSpectrum(ppmlim=lim)), mode='lines', name=name, line=linestyle) return fig.add_trace(trace) fig = addline(fig, plotIn, plotlim, 'Uncorrected', lines['in']) fig = addline(fig, plotOut, plotlim, 'Corrected', lines['out']) # Axes layout plotAxesStyle(fig, plotlim, title='Apodization summary') # Generate report if html is not None: from plotly.offline import plot from fsl_mrs.utils.preproc.reporting import figgroup, singleReport from datetime import datetime import os.path as op if op.isdir(html): filename = 'report_' + datetime.now().strftime( "%Y%m%d_%H%M%S%f")[:-3] + '.html' htmlfile = op.join(html, filename) elif op.isdir(op.dirname(html)) and op.splitext(html)[1] == '.html': htmlfile = html else: raise ValueError('Report html path must be file or directory. ') opName = 'Apodization' timestr = datetime.now().strftime("%H:%M:%S") datestr = datetime.now().strftime("%d/%m/%Y") headerinfo = 'Report for fsl_mrs.utils.preproc.filtering.apodize.\n'\ + f'Generated at {timestr} on {datestr}.' # Figures div = plot(fig, output_type='div', include_plotlyjs='cdn') figurelist = [ figgroup(fig=div, name='', foretext=f'Apodization of spectra.', afttext=f'') ] singleReport(htmlfile, opName, headerinfo, figurelist) return fig else: return fig
def phase_freq_align_diff_report(inFIDs0, inFIDs1, outFIDs0, outFIDs1, hdr, eps, phi, ppmlim=None, diffType='add', shift=True, html=None): from fsl_mrs.utils.preproc.combine import combine_FIDs import plotly.graph_objects as go from fsl_mrs.utils.preproc.reporting import plotStyles, plotAxesStyle from plotly.subplots import make_subplots # Fetch line styles lines, _, _ = plotStyles() # Make a new figure fig = make_subplots(rows=1, cols=2, subplot_titles=['Phase', 'Shift']) trace1 = go.Scatter(x=np.arange(1, len(phi) + 1), y=np.array(phi) * (180.0 / np.pi), mode='lines', name='Phase', line=lines['out']) fig.add_trace(trace1, row=1, col=1) fig.layout.xaxis.update(title_text='Transient #') fig.layout.yaxis.update(title_text=r'$\phi$ (degrees)') trace2 = go.Scatter(x=np.arange(1, len(eps) + 1), y=eps, mode='lines', name='Shift', line=lines['diff']) fig.add_trace(trace2, row=1, col=2) fig.layout.yaxis2.update(title_text='Shift (Hz)') fig.layout.xaxis2.update(title_text='Transient #') diffFIDListIn = [] diffFIDListOut = [] for fid0i, fid1i, fid0o, fid1o in zip(inFIDs0, inFIDs1, outFIDs0, outFIDs1): if diffType.lower() == 'add': diffFIDListIn.append(add(fid1i, fid0i)) diffFIDListOut.append(add(fid1o, fid0o)) elif diffType.lower() == 'sub': diffFIDListIn.append(subtract(fid1i, fid0i)) diffFIDListOut.append(subtract(fid1o, fid0o)) else: raise ValueError('diffType must be add or sub.') meanIn = combine_FIDs(diffFIDListIn, 'mean') meanOut = combine_FIDs(diffFIDListOut, 'mean') toMRSobj = lambda fid: MRS(FID=fid, header=hdr) meanIn = toMRSobj(meanIn) meanOut = toMRSobj(meanOut) if shift: axis = 'ppmshift' else: axis = 'ppm' toPlotIn, toPlotOut = [], [] for fid in diffFIDListIn: toPlotIn.append(toMRSobj(fid)) for fid in diffFIDListOut: toPlotOut.append(toMRSobj(fid)) def addline(fig, mrs, lim, name, linestyle): trace = go.Scatter(x=mrs.getAxes(ppmlim=lim, axis=axis), y=np.real(mrs.getSpectrum(ppmlim=lim, shift=shift)), mode='lines', name=name, line=linestyle) return fig.add_trace(trace) fig2 = go.Figure() for idx, fid in enumerate(toPlotIn): cval = np.round(255 * idx / len(toPlotIn)) linetmp = {'color': f'rgb(0,{cval},{cval})', 'width': 1} fig2 = addline(fig2, fid, ppmlim, f'#{idx}', linetmp) fig2 = addline(fig2, meanIn, ppmlim, f'Mean - Unligned', lines['blk']) plotAxesStyle(fig2, ppmlim, 'Unaligned') fig3 = go.Figure() for idx, fid in enumerate(toPlotOut): cval = np.round(255 * idx / len(toPlotIn)) linetmp = {'color': f'rgb(0,{cval},{cval})', 'width': 1} fig3 = addline(fig3, fid, ppmlim, f'#{idx}', linetmp) fig3 = addline(fig3, meanIn, ppmlim, f'Mean - Unligned', lines['out']) fig3 = addline(fig3, meanOut, ppmlim, f'Mean - Aligned', lines['blk']) plotAxesStyle(fig3, ppmlim, 'Aligned') if html is not None: from plotly.offline import plot from fsl_mrs.utils.preproc.reporting import figgroup, singleReport from datetime import datetime import os.path as op if op.isdir(html): filename = 'report_' + datetime.now().strftime( "%Y%m%d_%H%M%S%f")[:-3] + '.html' htmlfile = op.join(html, filename) elif op.isdir(op.dirname(html)) and op.splitext(html)[1] == '.html': htmlfile = html else: raise ValueError('Report html path must be file or directory. ') opName = 'AlignDiff' timestr = datetime.now().strftime("%H:%M:%S") datestr = datetime.now().strftime("%d/%m/%Y") headerinfo = 'Report for fsl_mrs.utils.align.phase_freq_align_diff.\n'\ + f'Generated at {timestr} on {datestr}.' # Figures div = plot(fig, output_type='div', include_plotlyjs='cdn') figurelist = [ figgroup(fig=div, name='', foretext=f'Alignment parameters.', afttext=f'') ] div2 = plot(fig2, output_type='div', include_plotlyjs='cdn') figurelist.append( figgroup(fig=div2, name='', foretext=f'Transients before alignment.', afttext=f'')) div3 = plot(fig3, output_type='div', include_plotlyjs='cdn') figurelist.append( figgroup(fig=div3, name='', foretext=f'Transients after alignment.', afttext=f'')) singleReport(htmlfile, opName, headerinfo, figurelist) return fig, fig2, fig3 else: return fig, fig2, fig3
def identifyUnlikeFIDs_report(goodFIDs,badFIDs,hdr,keepIndicies,rmIndicies,metric,ppmlim=(0.2,4.2),sdlimit = 1.96,html=None): from fsl_mrs.utils.preproc.combine import combine_FIDs import plotly.graph_objects as go from fsl_mrs.utils.preproc.reporting import plotStyles,plotAxesStyle metricGd = np.array(metric)[keepIndicies] metricBd = np.array(metric)[rmIndicies] metric_avg = np.mean(metric) metric_std = np.std(metric) metricGd_SD = np.abs(metricGd-metric_avg)/metric_std metricBd_SD = np.abs(metricBd-metric_avg)/metric_std gdIndex = np.argsort(metricGd_SD) bdIndex = np.argsort(metricBd_SD) plotGood,plotBad = [],[] gdLegend,bdLegend = [],[] toMRSobj = lambda fid : MRS(FID=fid,header=hdr) for idx in gdIndex: fid = goodFIDs[idx] plotGood.append(toMRSobj(fid)) gdLegend.append(f'Kept (SD={metricGd_SD[idx]:0.2f})') for idx in bdIndex: fid = badFIDs[idx] plotBad.append(toMRSobj(fid)) bdLegend.append(f'Removed (SD={metricBd_SD[idx]:0.2f})') target = get_target_FID(goodFIDs,target='median') tgtmrs = toMRSobj(target) # Fetch line styles lines,colors,_ = plotStyles() # Make a new figure fig = go.Figure() # Add lines to figure def addline(fig,mrs,lim,name,linestyle): trace = go.Scatter(x=mrs.getAxes(ppmlim=lim), y=np.real(mrs.getSpectrum(ppmlim=lim)), mode='lines', name=name, line=linestyle) return fig.add_trace(trace) for fid,leg in zip(plotGood,gdLegend): fig = addline(fig,fid,ppmlim,leg,lines['out']) for fid,leg in zip(plotBad,bdLegend): fig = addline(fig,fid,ppmlim,leg,lines['emph']) fig = addline(fig,tgtmrs,ppmlim,'Target',lines['blk']) plotAxesStyle(fig,ppmlim,title = 'Bad average removal summary') # Generate report if html is not None: from plotly.offline import plot from fsl_mrs.utils.preproc.reporting import figgroup, singleReport from datetime import datetime import os.path as op if op.isdir(html): filename = 'report_' + datetime.now().strftime("%Y%m%d_%H%M%S%f")[:-3]+'.html' htmlfile=op.join(html,filename) elif op.isdir(op.dirname(html)) and op.splitext(html)[1]=='.html': htmlfile = html else: raise ValueError('Report html path must be file or directory. ') opName = 'BadAverageRemoval' timestr = datetime.now().strftime("%H:%M:%S") datestr = datetime.now().strftime("%d/%m/%Y") headerinfo = 'Report for fsl_mrs.utils.preproc.unlike.identifyUnlikeFIDs.\n'\ + f'Generated at {timestr} on {datestr}.' # Figures div = plot(fig, output_type='div',include_plotlyjs='cdn') figurelist = [figgroup(fig = div, name= '', foretext= f'Identification of FIDs unlike others. SD limit = {sdlimit:0.2f}', afttext= f'')] singleReport(htmlfile,opName,headerinfo,figurelist) return fig else: return fig
def phaseCorrect_report(inFID, outFID, hdr, position, ppmlim=(2.8, 3.2), html=None): """ Generate report for phaseCorrect """ # from matplotlib import pyplot as plt from fsl_mrs.core import MRS import plotly.graph_objects as go from fsl_mrs.utils.preproc.reporting import plotStyles, plotAxesStyle # Turn input FIDs into mrs objects toMRSobj = lambda fid: MRS(FID=fid, header=hdr) plotIn = toMRSobj(inFID) plotOut = toMRSobj(outFID) widelimit = (0, 6) # Fetch line styles lines, colors, _ = plotStyles() # Make a new figure fig = go.Figure() # Add lines to figure def addline(fig, mrs, lim, name, linestyle): trace = go.Scatter(x=mrs.getAxes(ppmlim=lim), y=np.real(mrs.getSpectrum(ppmlim=lim)), mode='lines', name=name, line=linestyle) return fig.add_trace(trace) fig = addline(fig, plotIn, widelimit, 'Unphased', lines['in']) fig = addline(fig, plotIn, ppmlim, 'Search region', lines['emph']) if position is None: # re-estimate here. position = np.argmax(np.abs(plotIn.getSpectrum(ppmlim=ppmlim))) axis = [plotIn.getAxes(ppmlim=ppmlim)[position]] y_data = [np.real(plotIn.getSpectrum(ppmlim=ppmlim))[position]] trace = go.Scatter(x=axis, y=y_data, mode='markers', name='max point', marker=dict(color=colors['emph'], symbol='x', size=8)) fig.add_trace(trace) fig = addline(fig, plotOut, widelimit, 'Phased', lines['out']) # Axes layout plotAxesStyle(fig, widelimit, title='Phase correction summary') # Axes if html is not None: from plotly.offline import plot from fsl_mrs.utils.preproc.reporting import figgroup, singleReport from datetime import datetime import os.path as op if op.isdir(html): filename = 'report_' + datetime.now().strftime( "%Y%m%d_%H%M%S%f")[:-3] + '.html' htmlfile = op.join(html, filename) elif op.isdir(op.dirname(html)) and op.splitext(html)[1] == '.html': htmlfile = html else: raise ValueError('Report html path must be file or directory. ') opName = 'Phase correction' timestr = datetime.now().strftime("%H:%M:%S") datestr = datetime.now().strftime("%d/%m/%Y") headerinfo = 'Report for fsl_mrs.utils.preproc.phasing.phaseCorrect.\n'\ + f'Generated at {timestr} on {datestr}.' # Figures div = plot(fig, output_type='div', include_plotlyjs='cdn') figurelist = [ figgroup( fig=div, name='', foretext= f'Phase correction of spectra based on maximum in the range {ppmlim[0]} to {ppmlim[1]} ppm.', afttext=f'') ] singleReport(htmlfile, opName, headerinfo, figurelist) return fig else: return fig