pyPOCQuant with Jupyter

Demo notebook to show the usage of pyPOCQuant using a Jupyter/IPython notebook.

This is a convinient way to automate the execution of multiple folders and directly analize and plot the results.

[4]:
# Load the relevant dependencies
import os
import sys
import pandas as pd
sys.path.append('..\..')
from pypocquant.lib.pipeline import run_pipeline
from pypocquant.lib.settings import load_settings
from pathlib import Path
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from IPython.display import Image, display

Next lets load and print the example config

[8]:
p = Path(os.path.abspath('images'))
settings_file_path = Path(p.parent / 'config.conf')
print('The pipeline will be run with the following configuration')
f = open(str(settings_file_path), "r")
print(f.read())
The pipeline will be run with the following configuration
max_workers=4
qc=True
verbose=True
control_band_index=-1
sensor_band_names=('igm', 'igg', 'ctl')
peak_expected_relative_location=(0.31, 0.53, 0.75)
sensor_center=(147, 522)
sensor_size=(45, 215)
sensor_border=(7, 7)
perform_sensor_search=True
qr_code_border=40
subtract_background=True
sensor_search_area=(55, 225)
sensor_thresh_factor=2.0
raw_auto_stretch=False
raw_auto_wb=False
strip_try_correct_orientation=False
strip_try_correct_orientation_rects=(0.52, 0.15, 0.09)
strip_text_to_search=''
strip_text_on_right=False
force_fid_search=False

[9]:
if settings_file_path.exists():
    input_folder_path = Path(p)
    results_folder_path = Path(input_folder_path / 'pipeline')
    results_folder_path.mkdir(parents=True, exist_ok=True)
    print(f'RUN pipeline for {p}')

    ## Load the settings
    settings = load_settings(settings_file_path)

    ## Run the pipeline
    run_pipeline(
        input_folder_path,
        results_folder_path,
        **settings
    )
  0%|                                                                                            | 0/7 [00:00<?, ?it/s]
RUN pipeline for C:\Users\Localadmin\Documents\pypocquantui\src\main\python\pyPOCQuantUI\pypocquant\examples\images
100%|████████████████████████████████████████████████████████████████████████████████████| 7/7 [00:10<00:00,  1.52s/it]
Results written to C:\Users\Localadmin\Documents\pypocquantui\src\main\python\pyPOCQuantUI\pypocquant\examples\images\pipeline\quantification_data.csv
Logfile written to C:\Users\Localadmin\Documents\pypocquantui\src\main\python\pyPOCQuantUI\pypocquant\examples\images\pipeline\log.txt
Settings written to C:\Users\Localadmin\Documents\pypocquantui\src\main\python\pyPOCQuantUI\pypocquant\examples\images\pipeline\settings.conf
Pipeline completed.

Read and plot the results

[10]:
results = pd.read_csv(str(Path(p / 'pipeline/quantification_data.csv')))
results
[10]:
fid fid_num filename extension basename iso_date iso_time exp_time f_number focal_length_35_mm ... igm igm_abs igm_ratio igg igg_abs igg_ratio ctl ctl_abs ctl_ratio user
0 H01601828610122 1601828610122 IMG_9067.JPG .JPG IMG_9067 2020-06-21 12-14-03 [1/10] [63/10] -1 ... 0 0.000000 0.000000 0 0.000000 0.000000 1 1087.000925 1.0 CUNYA
1 F5921394 5921394 IMG_9068.JPG .JPG IMG_9068 2020-06-21 12-14-46 [1/10] [63/10] -1 ... 1 822.735949 0.805935 1 1443.824091 1.414340 1 1020.846550 1.0 CUNYA
2 F5922180 5922180 IMG_9069.JPG .JPG IMG_9069 2020-06-21 12-15-07 [1/10] [63/10] -1 ... 1 200.968865 0.194804 1 1029.903783 0.998311 1 1031.645989 1.0 CUNYA
3 F5922944 5922944 IMG_9070.JPG .JPG IMG_9070 2020-06-21 12-15-28 [1/10] [63/10] -1 ... 0 0.000000 0.000000 1 405.080753 0.403488 1 1003.946928 1.0 CUNYA

4 rows × 25 columns

[11]:
%matplotlib inline
dm = pd.melt(results, id_vars=['fid'], value_vars=['igm', 'igg', 'ctl', 'igm_abs', 'igg_abs', 'ctl_abs', 'igm_ratio', 'igg_ratio', 'ctl_ratio'])
g = sns.catplot(x="fid", y="value", hue="fid", col='variable', col_wrap=6, data=dm, sharey=False, height=1, aspect=1.6)
g.set_xticklabels(rotation=90)

axes = g.axes.flatten()
titles = ['igm', 'igg', 'ctl', 'igm_abs', 'igg_abs', 'ctl_abs', 'igm_ratio', 'igg_ratio', 'ctl_ratio']
limits = [[-0.05,1.15], [-0.05,1.15], [-0.05,1.15], [-80,1500], [-80,1550], [-80,1500],
          [-0.08,1.5], [-0.08,1.5], [-0.08,1.5]]
for ix, ax in enumerate(axes):
    ax.set_title(titles[ix])
    ax.set_ylim(limits[ix])
g.savefig("output.pdf", dpi=300)
_images/example_nb_8_0.png

Check the qc images

[12]:
i1 = Image(filename=str(Path(p / 'pipeline/IMG_9068_JPG_peak_analysis.PNG')))
i2 = Image(filename=str(Path(p / 'pipeline/IMG_9068_JPG_peak_overlays.PNG')))
i3 = Image(filename=str(Path(p / 'pipeline/IMG_9068_JPG_strip_gray_aligned.PNG')))
i4 = Image(filename=str(Path(p / 'pipeline/IMG_9068_JPG_rotated.JPG')))
display(i1, i2, i3, i4)
_images/example_nb_10_0.png
_images/example_nb_10_1.png
_images/example_nb_10_2.png
_images/example_nb_10_3.jpeg

Inspect the log file

[14]:
f = open(str(Path(p / 'pipeline/log.txt')), "r")
print(f.read())
f.close()

File = 20210105_config_run_1.conf

File = IMG_9067.JPG
Processing IMG_9067.JPG
Best percentiles for barcode extraction: (0, 100); best scaling factor = 0.25; score = 6/6
Detected FIDs for rotated image: H01601828610122 H01601828610122
File IMG_9067.JPG: best percentiles for barcode extraction after rotation: (0, 100); best scaling factor = 0.5; score = 6/6
File IMG_9067.JPG: Strip box image rotated by angle -0.285863954857813 degrees using QR code locations.
File IMG_9067.JPG: FID = 'H01601828610122'
File IMG_9067.JPG: sensor coordinates = [126, 171, 423, 638], score = 1.0
Peak 143 has lower bound 99 (d = 44) with relative intensity 0.00 and upper bound 166 (d = 23) with relative intensity 0.00. Band width is 68. Band skewness is 0.52
File IMG_9067.JPG: the bands were 'normal'.
✓ File IMG_9067.JPG: successfully processed and added to results table.

File = IMG_9068.JPG
Processing IMG_9068.JPG
Best percentiles for barcode extraction: (0, 100); best scaling factor = 0.25; score = 6/6
Detected FIDs for rotated image: F5921394 F5921394
File IMG_9068.JPG: best percentiles for barcode extraction after rotation: (0, 100); best scaling factor = 0.25; score = 6/6
File IMG_9068.JPG: Strip box image rotated by angle -0.32740089084438817 degrees using QR code locations.
File IMG_9068.JPG: FID = 'F5921394'
File IMG_9068.JPG: sensor coordinates = [126, 171, 416, 631], score = 1.0
Peak 65 has lower bound 45 (d = 20) with relative intensity 0.00 and upper bound 83 (d = 18) with relative intensity 0.01. Band width is 39. Band skewness is 0.90
Peak 112 has lower bound 90 (d = 22) with relative intensity 0.01 and upper bound 142 (d = 30) with relative intensity 0.00. Band width is 53. Band skewness is 1.36
Peak 159 has lower bound 138 (d = 21) with relative intensity 0.00 and upper bound 201 (d = 42) with relative intensity 0.00. Band width is 64. Band skewness is 2.00
File IMG_9068.JPG: the bands were 'normal'.
✓ File IMG_9068.JPG: successfully processed and added to results table.

File = IMG_9069.JPG
Processing IMG_9069.JPG
Best percentiles for barcode extraction: (0, 100); best scaling factor = 0.5; score = 6/6
Detected FIDs for rotated image: F5922180 F5922180
File IMG_9069.JPG: best percentiles for barcode extraction after rotation: (0, 100); best scaling factor = 0.5; score = 6/6
File IMG_9069.JPG: Strip box image rotated by angle -0.28627203365974213 degrees using QR code locations.
File IMG_9069.JPG: FID = 'F5922180'
File IMG_9069.JPG: sensor coordinates = [126, 171, 416, 631], score = 1.0
Peak 65 has lower bound 43 (d = 22) with relative intensity 0.00 and upper bound 79 (d = 14) with relative intensity 0.03. Band width is 37. Band skewness is 0.64
Peak 112 has lower bound 89 (d = 23) with relative intensity 0.00 and upper bound 143 (d = 31) with relative intensity 0.00. Band width is 55. Band skewness is 1.35
Peak 158 has lower bound 133 (d = 25) with relative intensity 0.00 and upper bound 200 (d = 42) with relative intensity 0.00. Band width is 68. Band skewness is 1.68
File IMG_9069.JPG: the bands were 'normal'.
✓ File IMG_9069.JPG: successfully processed and added to results table.

File = IMG_9070.JPG
Processing IMG_9070.JPG
Best percentiles for barcode extraction: (0, 100); best scaling factor = 0.25; score = 6/6
Detected FIDs for rotated image: F5922944 F5922944
File IMG_9070.JPG: best percentiles for barcode extraction after rotation: (0, 100); best scaling factor = 0.5; score = 6/6
File IMG_9070.JPG: Strip box image rotated by angle -0.4086648209901469 degrees using QR code locations.
File IMG_9070.JPG: FID = 'F5922944'
File IMG_9070.JPG: sensor coordinates = [126, 171, 424, 639], score = 1.0
Peak 96 has lower bound 76 (d = 20) with relative intensity 0.01 and upper bound 122 (d = 26) with relative intensity 0.00. Band width is 47. Band skewness is 1.30
Peak 141 has lower bound 122 (d = 19) with relative intensity 0.01 and upper bound 190 (d = 49) with relative intensity 0.00. Band width is 69. Band skewness is 2.58
File IMG_9070.JPG: the bands were 'normal'.
✓ File IMG_9070.JPG: successfully processed and added to results table.

File = pipeline

File = test

c:\users\localadmin\appdata\local\programs\python\python36\lib\site-packages\ipykernel_launcher.py:1: ResourceWarning: unclosed file <_io.TextIOWrapper name='C:\\Users\\Localadmin\\Documents\\pypocquantui\\src\\main\\python\\pyPOCQuantUI\\pypocquant\\examples\\images\\pipeline\\log.txt' mode='r' encoding='cp1252'>
  """Entry point for launching an IPython kernel.