From a261546b2c021e12864aa87a997a08a4a79a5fd4 Mon Sep 17 00:00:00 2001 From: Antonino Ingargiola Date: Mon, 15 Apr 2019 21:28:34 +0200 Subject: [PATCH 1/4] Docs: fix typos --- phconvert/pqreader.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/phconvert/pqreader.py b/phconvert/pqreader.py index b5c6cac..c7259a9 100644 --- a/phconvert/pqreader.py +++ b/phconvert/pqreader.py @@ -163,7 +163,7 @@ def load_phu(filename): A tuple of histograms, histogram resolution, and tags. The latter is an dictionary of tags contained in the file header. Each item in the dictionary has 'idx', 'type', - 'value' amd 'offset' keys. Some tags also have a 'data' key. + 'value' and 'offset' keys. Some tags also have a 'data' key. Use :func:`_ptu_print_tags` to print the tags as an easy-to-read table. """ @@ -583,9 +583,9 @@ def phu_reader(filename): s = f.read() tags, _ = _read_header_tags(s) - # one as to loop over the different curves (histogram) stored in the phu file + # one has to loop over the different curves (histogram) stored in the phu file Ncurves = tags['HistoResult_NumberOfCurves']['value'] - # all Nbins should be equal between the Ncurves but there is as many tags as curves + # all Nbins should be equal between the Ncurves but there are as many tags as curves Nbins = tags['HistResDscr_HistogramBins'][0]['value'] histograms = np.zeros((Nbins,Ncurves), dtype='uint32') From 6fd17c3d9612cbb064499615123fb4df1b824757 Mon Sep 17 00:00:00 2001 From: Antonino Ingargiola Date: Mon, 15 Apr 2019 21:29:24 +0200 Subject: [PATCH 2/4] Swap histogram array axis for PHU files --- phconvert/pqreader.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phconvert/pqreader.py b/phconvert/pqreader.py index c7259a9..a4b0d43 100644 --- a/phconvert/pqreader.py +++ b/phconvert/pqreader.py @@ -587,12 +587,12 @@ def phu_reader(filename): Ncurves = tags['HistoResult_NumberOfCurves']['value'] # all Nbins should be equal between the Ncurves but there are as many tags as curves Nbins = tags['HistResDscr_HistogramBins'][0]['value'] - histograms = np.zeros((Nbins,Ncurves), dtype='uint32') + histograms = np.zeros((Ncurves, Nbins), dtype='uint32') # populate histograms and get some metadata histo_resolution=[] for ind_curve in range(Ncurves): - histograms[:, ind_curve] = np.frombuffer(s, dtype='uint32', + histograms[ind_curve] = np.frombuffer(s, dtype='uint32', count=tags['HistResDscr_HistogramBins'][ind_curve]['value'], offset=tags['HistResDscr_DataOffset'][ind_curve]['value']) histo_resolution.append( From 6a98132b9ec5327fad5f64fa0d6f4f9de7ffbc68 Mon Sep 17 00:00:00 2001 From: Antonino Ingargiola Date: Mon, 15 Apr 2019 21:29:43 +0200 Subject: [PATCH 3/4] PHU: add unit tests --- phconvert/test_pqreader.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/phconvert/test_pqreader.py b/phconvert/test_pqreader.py index b81a1c8..2aac9fe 100644 --- a/phconvert/test_pqreader.py +++ b/phconvert/test_pqreader.py @@ -131,3 +131,36 @@ def test_load_pt3(): acq_duration2 = (timestamps[-1] - timestamps[0]) * meta['timestamps_unit'] # The two acquisition times should match. TODO: find out why they don't #assert abs(acq_duration - acq_duration2) < 0.1 ## BROKEN TEST! + + +def test_load_phu(): + """Test loading PT3 files.""" + fn = 'nanodiamant_histo.phu' + filename = DATADIR + fn + assert os.path.isfile(filename), 'File not found: %s' % filename + hist, bin_size, meta = phc.pqreader.load_phu(filename) + + # test acquisition duration + acq_duration = meta['tags']['MeasDesc_AcquisitionTime']['value'] * 1e-3 + acq_duration2 = meta['acquisition_duration'] + assert acq_duration == acq_duration2 == 10 + + # test hist.shape + tags = meta['tags'] + num_curves = tags['HistoResult_NumberOfCurves']['value'] + num_bins = [tag['value'] for tag in tags['HistResDscr_HistogramBins']] + assert hist.shape[1] == num_bins[0] + assert hist.shape[0] == len(bin_size) == num_curves + + # all value in `num_bins` and in `bin_size` must be the same + def all_values_equal(x): + return all(np.array(x) == x[0]) + assert all_values_equal(num_bins) + assert all_values_equal(bin_size) + + # test `bin_size` + bin_size2 = [tag['value'] for tag in tags['HistResDscr_MDescResolution']] + assert np.array_equal(bin_size, bin_size2) + + + From 8d4c7046fbcea1abc7deaba1da827440fd49b41c Mon Sep 17 00:00:00 2001 From: Antonino Ingargiola Date: Mon, 15 Apr 2019 21:44:10 +0200 Subject: [PATCH 4/4] PHU: add example notebook and enable CI --- .travis.yml | 1 + appveyor.yml | 1 + .../Example reading PicoQuant PHU files.ipynb | 157 ++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 notebooks/Example reading PicoQuant PHU files.ipynb diff --git a/.travis.yml b/.travis.yml index 855a6e6..bdf519e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,6 +44,7 @@ before_script: - wget https://ndownloader.figshare.com/files/14828594 -O 20161027_DM1_1nM_pH7_20MHz1.ptu - wget https://ndownloader.figshare.com/files/13675271 -O TestFile_2.ptu - wget https://ndownloader.figshare.com/files/14850533 -O trace_T2_300s_1_coincidence.ptu + - wget https://ndownloader.figshare.com/files/14890535 -O nanodiamant_histo.phu - wget https://github.com/dwaithe/FCS_point_correlator/raw/master/focuspoint/topfluorPE_2_1_1_1.pt3 - wget https://github.com/Photon-HDF5/phconvert/files/1380341/DNA_FRET_0.5nM.pt3.zip - unzip DNA_FRET_0.5nM.pt3.zip diff --git a/appveyor.yml b/appveyor.yml index 9941d91..c9854d5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -48,6 +48,7 @@ before_test: - ps: wget https://ndownloader.figshare.com/files/14828594 -O 20161027_DM1_1nM_pH7_20MHz1.ptu - ps: wget https://ndownloader.figshare.com/files/13675271 -OutFile TestFile_2.ptu - ps: wget https://ndownloader.figshare.com/files/14850533 -O trace_T2_300s_1_coincidence.ptu + - ps: wget https://ndownloader.figshare.com/files/14890535 -O nanodiamant_histo.phu - ps: wget https://github.com/dwaithe/FCS_point_correlator/raw/master/focuspoint/topfluorPE_2_1_1_1.pt3 -OutFile topfluorPE_2_1_1_1.pt3 - ps: wget https://github.com/Photon-HDF5/phconvert/files/1380341/DNA_FRET_0.5nM.pt3.zip -OutFile DNA_FRET_0.5nM.pt3.zip - 7z e DNA_FRET_0.5nM.pt3.zip diff --git a/notebooks/Example reading PicoQuant PHU files.ipynb b/notebooks/Example reading PicoQuant PHU files.ipynb new file mode 100644 index 0000000..681044d --- /dev/null +++ b/notebooks/Example reading PicoQuant PHU files.ipynb @@ -0,0 +1,157 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "filename = 'data/nanodiamant_histo.phu'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import phconvert as phc\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hist, bin_size, meta = phc.pqreader.load_phu(filename)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hist.shape # the array containing all the histograms" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bin_size # one bin size per histogram" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "assert all(bin_size == bin_size[0]) # all curves must have the same bin size" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "meta.keys()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "meta['acquisition_duration'] # in seconds" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "n = 600\n", + "ns = 1e9\n", + "time = np.arange(hist.shape[1]) * bin_size[0] # in s\n", + "\n", + "for i in range(hist.shape[0]):\n", + " plt.plot(time * ns, hist[i], label=f'Curve {i}')\n", + "plt.xlabel('Time (ns)');\n", + "plt.legend()\n", + "plt.xlim(-10, 125)\n", + "plt.grid();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "phc.pqreader._ptu_print_tags(meta['tags'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.equal([1,2,3], [1,2,3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.alltrue" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "py37-sm", + "language": "python", + "name": "py37-sm" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.2" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}