def test_shiftToRef(): testFIDs, testHdrs = syn.syntheticFID(amplitude=[1, 0], chemicalshift=[-2.1, 0], phase=[0, 0], points=1024, noisecovariance=[[1E-3]]) shiftFID, _ = preproc.shiftToRef(testFIDs[0], -2.0, testHdrs['bandwidth'], testHdrs['centralFrequency'], ppmlim=(-2.2, -2.0), shift=False) mrs = MRS(FID=shiftFID, header=testHdrs) maxindex = np.argmax(mrs.getSpectrum(shift=False)) position = mrs.getAxes(axis='ppm')[maxindex] assert np.isclose(position, -2.0, atol=1E-1)
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 test_calcQC(): # Syntetic data synFID, synHdr = syntheticFID(noisecovariance=[[0.1]], points=2 * 2048, chemicalshift=[0], amplitude=[6.0], linewidth=[10]) synFIDNoise, synHdrNoise = syntheticFID(noisecovariance=[[0.1]], points=2 * 2048, chemicalshift=[0], amplitude=[0], linewidth=[10]) basisFID, basisHdr = syntheticFID(noisecovariance=[[0.0]], points=2 * 2048, chemicalshift=[0], amplitude=[0.1], linewidth=[2]) synMRS = MRS(FID=synFID[0], header=synHdr) synMRSNoise = MRS(FID=synFIDNoise[0], header=synHdrNoise) synMRSNoNoise = MRS(FID=synHdr['noiseless'], header=synHdr) synMRS_basis = MRS(FID=synFID[0], header=synHdr, basis=basisFID[0], basis_hdr=basisHdr, names=['Peak1']) truenoiseSD = np.sqrt(synHdrNoise['cov'][0, 0]) pureNoiseMeasured = np.std(synMRSNoise.getSpectrum()) realnoise = np.std(np.real(synMRSNoise.getSpectrum())) imagNoise = np.std(np.imag(synMRSNoise.getSpectrum())) print( f'True cmplx noise = {truenoiseSD:0.3f}, pure noise measured = {pureNoiseMeasured:0.3f} (real/imag = {realnoise:0.3f}/{imagNoise:0.3f})' ) # Calc SNR without apodisation from the no noise and pure noise spectra truePeakHeight = np.max(np.real(synMRSNoNoise.getSpectrum())) SNR_noApod = truePeakHeight / pureNoiseMeasured print( f'SNR no apod: {SNR_noApod:0.1f} ({truePeakHeight:0.2e}/{pureNoiseMeasured:0.2e})' ) # Calc SNR with apodisation from the no noise and pure noise spectra trueLW = synHdr['inputopts']['linewidth'][0] trueApodSpec_Noise = specApodise(synMRSNoise, trueLW) apodNoise = np.std(trueApodSpec_Noise) trueApodSpec_noNoise = specApodise(synMRSNoNoise, trueLW) peakHeigtApod = np.max(np.real(trueApodSpec_noNoise)) SNR = peakHeigtApod / apodNoise print(f'SNR w. apod: {SNR:0.1f} ({peakHeigtApod:0.2e}/{apodNoise:0.2e})') metab_groups = [0] Fitargs = { 'ppmlim': [2.65, 6.65], 'method': 'Newton', 'baseline_order': -1, 'metab_groups': [0] } res = fit_FSLModel(synMRS_basis, **Fitargs) fwhm_test, SNRObj = calcQC(synMRS_basis, res, ppmlim=[2.65, 6.65]) print(f'Measured FWHM: {fwhm_test.mean().to_numpy()[0]:0.1f}') print(f'Measured spec SNR: {SNRObj.spectrum:0.1f}') print(f'Measured peak SNR: {SNRObj.peaks.mean().to_numpy()[0]:0.1f}') assert np.isclose(fwhm_test.mean().to_numpy(), trueLW, atol=1E0) assert np.isclose(SNRObj.spectrum, SNR_noApod, atol=1E1) assert np.isclose(SNRObj.peaks.mean().to_numpy(), SNR, atol=2E1)