Update model data

Importing all the packages to be used in this notebook

The following cell imports all the modules and functions required. Of note are lines 18 - 20 which import the custom electroninserts functions. These custom functions are located within electroninserts.py which can be perused to ensure it is running as you would expect.


In [1]:
import os

import dicom

from glob import glob

import zipfile
import time
import shutil
import datetime
import re
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

from IPython.core.display import display, Markdown

from bokeh.io import output_notebook, output_file, reset_output
from bokeh.plotting import show, save

from electroninserts import (
    parameterise_single_insert, display_parameterisation,
    convert2_ratio_perim_area, interactive, fallback_scatter)

print("All modules and functions successfully imported.")


All modules and functions successfully imported.

In [2]:
# !pip install --upgrade version_information
# %load_ext version_information
# %version_information dicom, electroninserts, re, numpy, pandas, matplotlib, bokeh, version_information


Requirement already up-to-date: version_information in c:\users\sbiggs\appdata\local\continuum\anaconda3\envs\electroninserts\lib\site-packages
Out[2]:
SoftwareVersion
Python3.5.2 64bit [MSC v.1900 64 bit (AMD64)]
IPython5.0.0
OSWindows 7 6.1.7601 SP1
dicom0.9.9
electroninserts0.1.0
re2.2.1
numpy1.11.1
pandas0.18.1
matplotlib1.5.1
bokeh0.11.1
version_information1.0.3
Fri Aug 05 16:13:58 2016 AUS Eastern Standard Time

Recording and loading the data

The following cells outline both your data itself the specific details of the data collection and definition. You can either write your own contents into the cells, or you can drag and drop the relevant files from your computer via windows explorer into the cell itself.

Once you have input your data to please consider uploading this data to http://simonbiggs.net/electrondata for the purpose of furthering this project.


In [3]:
# Archive old files to minimise confusion
old_data_files = glob('*.csv')
old_detail_files = glob('*.yaml')
old_report_files = glob('*.html')
old_zip_files = glob('*.zip')

old_files = np.concatenate([
        old_data_files, old_detail_files, old_report_files, old_zip_files])

for data_file in old_files:
    os.rename(data_file, "archive/{}".format(data_file))

In [4]:
%%writefile details.yaml
%YAML 1.1
---
Machine: Elekta Synergy Linac with Agility MLCs

R50 (cm):
    6 MeV: 2.45
    9 MeV: 3.47
    12 MeV: 4.72
    15 MeV: 5.8
    18 MeV: 7.2

Applicator factors:
    6 MeV:
        6x6 cm: 0.871
        10x10 cm: 1.000
        14x14 cm: 1.029
        20x20 cm: 1.022
        25x25 cm: 1.026
    9 MeV:
        6x6 cm: 0.919
        10x10 cm: 1.000
        14x14 cm: 0.981
        20x20 cm: 0.977
        25x25 cm: 0.971
    12 MeV:
        6x6 cm: 0.971
        10x10 cm: 1.000
        14x14 cm: 0.990
        20x20 cm: 0.985
        25x25 cm: 0.983
    15 MeV:
        6x6 cm: 0.980
        10x10 cm: 1.000
        14x14 cm: 0.982
        20x20 cm: 0.988
        25x25 cm: 0.987
    18 MeV:
        6x6 cm: 1.011
        10x10 cm: 1.000
        14x14 cm: 0.983
        20x20 cm: 0.979
        25x25 cm: 0.967

SSD factors:
    100 SSD: 1.000

Applicator sizes at isocentre:
    6x6 cm: 6.3x6.3 cm
    10x10 cm: 10.5x10.5 cm
    14x14 cm: 14.7x14.7 cm
    20x20 cm: 21.1x21.1 cm
    25x25 cm: 26.3x26.3 cm

Definition of modelled factor: >
    The factor given here is the insert factor defined as the portion of the 
    electron output factor that is dependent on the insert alone. The electron 
    output factor is defined as per AAPM TG 25  as the ratio of dose per 
    monitor unit at dmax.

Measurement details: >
    Insert factors were measured in RW3 with an Advanced Markus on an Elekta 
    Agility linac. When the depth of maximum dose was shifted from the reference 
    depth this depth was searched for to a 1 mm resolution. All depth differences 
    took into account stopping power ratio corrections as per the protocol in 
    IAEA TRS 398.

Insert shielding material: Cerrobend

Software license of accompanying data: AGPLv3+


Writing details.yaml

In [5]:
%%writefile data.csv
Label,Width (cm @ 100SSD),Length (cm @ 100SSD),Energy (MeV),Applicator (cm),SSD (cm),Insert factor (dose insert / dose open)
Simon 3cm circle,3.15,3.16,12,10,100,0.9294
Simon 3x5cm oval,3.16,5.25,12,10,100,0.9346
Simon 3x13cm oval,3.17,13.64,12,10,100,0.9533
Simon 3x6.5cm oval,3.17,6.83,12,10,100,0.9488
Simon 3x9cm oval,3.17,9.43,12,10,100,0.9488
P4,3.55,7.7,12,10,100,0.9443
Simon #57 cutout,3.66,5.04,12,10,100,0.9434
Simon #112 cutout,3.71,4.36,12,10,100,0.9488
Simon 4cm circle,4.2,4.21,12,10,100,0.956
Simon 4x10cm oval,4.21,10.51,12,10,100,0.9709
Simon 4x13cm oval,4.21,13.65,12,10,100,0.9756
Simon 4x6.5cm oval,4.21,6.82,12,10,100,0.9606
Simon 4x8cm oval,4.21,8.41,12,10,100,0.9709
Simon #20 cutout,4.38,5.47,12,10,100,0.9634
P10,4.48,7.29,12,10,100,0.9606
Simon #14 cutout,4.59,5.67,12,10,100,0.9588
Simon #3 cutout,4.59,6.54,12,10,100,0.9681
Simon #38 cutout,4.67,6.28,12,10,100,0.9737
Simon #22 cutout,5.21,11.4,12,10,100,0.9881
Simon 5cm circle,5.25,5.26,12,10,100,0.9709
Simon 5x10cm oval,5.26,10.52,12,10,100,0.9881
Simon 5x13cm oval,5.26,13.66,12,10,100,0.9872
Simon 5x8cm oval,5.26,8.41,12,10,100,0.9833
Simon #104 cutout,5.34,9.64,12,10,100,0.993
P40,5.43,11.02,12,10,100,0.9872
Simon #19 cutout,5.72,11.6,12,10,100,0.999
Simon #83 cutout,5.86,8.62,12,10,100,0.9891
Simon #58 cutout,6,7.98,12,10,100,0.9911
P3,6.04,9.22,12,10,100,0.999
Simon #33 cutout,6.08,6.64,12,10,100,0.993
Simon 6cm circle,6.3,6.33,12,10,100,0.9862
Simon #43 cutout,6.31,8.24,12,10,100,0.9921
Simon #82 cutout,6.41,8.69,12,10,100,0.999
Simon #16 cutout,6.53,10.99,12,10,100,1
Simon #109 cutout,6.54,8.41,12,10,100,0.993
Simon #106 cutout,6.64,9.81,12,10,100,0.999
Simon #34 cutout,6.78,10.98,12,10,100,1.007
P22,6.9,10.25,12,10,100,0.999
Simon #41 cutout,7.08,10.77,12,10,100,1.005
Simon #6 cutout,7.18,11.27,12,10,100,0.999
P38_1,7.21,9.03,12,10,100,1.0101
Simon 7cm circle,7.36,7.37,12,10,100,1.003
Simon #73 cutout,7.56,10.05,12,10,100,1.004
P12_1,7.6,10.26,12,10,100,1.0142
Simon #70 cutout,7.64,8.99,12,10,100,1.003
Simon #18 cutout,7.82,10.85,12,10,100,1.002
Simon #32 cutout,8.06,11.85,12,10,100,1.007
Simon 8cm circle,8.4,8.42,12,10,100,1.007
Simon 9cm circle,9.45,9.47,12,10,100,1.0081
Simon 5cm_15MeV,4.99,5,15,10,100,0.9747
P36_2,5.07,9.15,15,10,100,0.9911
Simon 5.3x12.5cm_15MeV,5.26,12.45,15,10,100,0.9921
Simon 6.1cm_15MeV,6.09,6.1,15,10,100,0.9794
Simon 6.7x12cm_15MeV,6.76,12,15,10,100,0.999
P5_2,6.97,9.79,15,10,100,0.996
Simon 7.25cm_15MeV,7.23,7.26,15,10,100,1.003
P28,7.4,9.25,15,10,100,1
P37_1,7.73,9.66,15,10,100,1.005
Simon 8.3cm_15MeV,8.28,8.3,15,10,100,1.005
Simon 8.5x10.9cm_15MeV,8.5,10.85,15,10,100,1.005
Simon 9.5cm_15MeV,9.49,9.5,15,10,100,1.0091
P31_1,4.9,9.4,18,10,100,0.9911
P36_1,4.9,9.4,18,10,100,0.994
Simon 5cm_18MeV,4.99,5,18,10,100,0.9823
Simon 5.3x12.5cm_18MeV,5.26,12.45,18,10,100,0.995
Simon 6.1cm_18MeV,6.09,6.1,18,10,100,0.9881
P37_4,6.67,9.28,18,10,100,1.0081
Simon 6.7x12cm_18MeV,6.76,12,18,10,100,0.999
P12_2,6.83,9.19,18,10,100,1.005
P13,7.1,8.79,18,10,100,0.997
Simon 7.25cm_18MeV,7.23,7.26,18,10,100,1.001
Simon 8.3cm_18MeV,8.28,8.3,18,10,100,1.003
Simon 8.5x10.9cm_18MeV,8.5,10.85,18,10,100,1.004
P42,9.14,11.32,18,10,100,0.998
Simon 9.5cm_18MeV,9.49,9.5,18,10,100,1.0081
P62,3.99,6.51,6,10,100,0.9643
P50,4.1,5.99,6,10,100,0.9662
Simon 5cm_6MeV,4.99,5,6,10,100,0.9766
Simon 5.3x12.5cm_6MeV,5.26,12.45,6,10,100,0.996
P7,5.69,7.58,6,10,100,0.995
Appears to be a standard 6cm P5_1,6,6,6,10,100,0.9887
P9_1,5.79,7.2,6,10,100,0.9852
Simon 6.1cm_6MeV,6.09,6.1,6,10,100,0.9901
P24,6.47,8.25,6,10,100,0.995
Simon 6.7x12cm_6MeV,6.76,12,6,10,100,0.998
Simon 7.25cm_6MeV,7.23,7.26,6,10,100,1.007
P35_2,7.43,10.3,6,10,100,0.994
Simon 8.3cm_6MeV,8.28,8.3,6,10,100,1.006
P6,8.5,10.73,6,10,100,0.999
Simon 8.5x10.9cm_6MeV,8.5,10.85,6,10,100,1.003
Simon 9.5cm_6MeV,9.49,9.5,6,10,100,1.005
P46,4.37,6.21,9,10,100,0.9606
Simon 5cm_9MeV,4.99,5,9,10,100,0.9588
P53,5.09,6.32,9,10,100,0.9756
Simon 5.3x12.5cm_9MeV,5.26,12.45,9,10,100,0.9901
P25,5.38,8.23,9,10,100,0.9852
P8,5.64,6.96,9,10,100,0.9775
Simon 6.1cm_9MeV,6.09,6.1,9,10,100,0.9823
P9_2,6.29,6.69,9,10,100,0.993
P34_3,6.72,10.23,9,10,100,0.997
Simon 6.7x12cm_9MeV,6.76,12,9,10,100,1
Simon 7.25cm_9MeV,7.23,7.26,9,10,100,1.005
Simon 8.3cm_9MeV,8.28,8.3,9,10,100,1.004
P34_2,8.37,10.6,9,10,100,0.997
Simon 8.5x10.9cm_9MeV,8.5,10.85,9,10,100,1.005
P17,8.6,9.81,9,10,100,1.0111
Simon 9.5cm_9MeV,9.49,9.5,9,10,100,1.007
P61,4.69,14.39,12,14,100,0.9901
P56,5.91,12.56,12,14,100,1.0091
P15_1,7.4,13.47,12,14,100,1.0101
P21,7.65,10.8,12,14,100,1.002
P45,9.11,12.34,12,14,100,1.0091
P19,7.08,8.84,15,14,100,1.0215
P15_2,8.57,12.91,15,14,100,1.0215
P27,9.25,11.42,15,14,100,1.0132
P37_3,7.3,12.97,18,14,100,1.0132
P38_2,8.69,11.49,18,14,100,1.0173
P33,6.21,10.43,6,14,100,0.999
P37_2,7.29,10.1,6,14,100,1.007
P20,8.6,9.24,6,14,100,1.006
P38_3,8.84,15.52,6,14,100,1.003
P16,9.05,11.99,6,14,100,1.0111
P35_1,9.28,10.58,6,14,100,1.0091
P23,9.87,13.16,6,14,100,1.005
P26,6.68,10.71,9,14,100,1.003
P14_2,7.03,12.47,9,14,100,1.0173
P34_1,7.66,11.25,9,14,100,1.006
P18,8.6,10.32,9,14,100,1.0101
P14_1,8.61,12.03,9,14,100,1.0163
P31_2,10.65,17.74,18,20,100,1.0142
P60,18.48,20.89,6,20,100,1.004
P41,7.85,24.61,9,20,100,1.0111
P32,9.3,22.7,9,20,100,1.0111
P51,10,28.65,15,25,100,1.0142
P49,2.69,4.21,6,6,100,0.8961
P43,2.8,2.9,6,6,100,0.885
P48,3.31,6.08,6,6,100,0.969
P47,3.39,3.4,6,6,100,0.9083
P35_3,3.48,4.78,6,6,100,0.939
Standard 4cm circle P63,4,4,6,6,100,0.9425
P59,4.1,5.89,6,6,100,0.9814
Standard 5cm circle P29,5,5,6,6,100,0.9891
P30,4.12,5.22,9,6,100,0.9597
P2,4.43,5.97,9,6,100,0.9728
P52,4.89,5.6,9,6,100,0.999
Appears to be a standard 6cm P58,6,6,9,6,100,1.002
P64,8.96,13.21,9,14,100,1.0121
P65 parameterised by hand,8.4,10.7,15,14,100,1.003


Writing data.csv

Timestamping your data and details files and optionally uploading these for others to make use of

Now that you have created your details and data files these are to be timestamped for later reference. Please consider giving back to this project by uncommenting the final lines of this cell which will add these two newly created files to this public dropbox folder — http://simonbiggs.net/electrondata. To uncomment these lines, select them and press Ctrl + /.


In [6]:
# Create a timestamp for data and reports and rename the data file
timestamp = datetime.datetime.fromtimestamp(time.time()).strftime('%Y%m%d%H%M%S')

data_filename = "{}_data.csv".format(timestamp)
details_filename = "{}_details.yaml".format(timestamp)
shutil.move("data.csv", data_filename)
shutil.move("details.yaml", details_filename)

# # Uncomment these lines to give back to this project
# import dropbox

# simonbiggs_electroninserts_accesstoken = '5_VQ4CH7dO0AAAAAAAAhYhsClbUdrEnWKvMMnWagVXqKDTlTdf45ZwlKBp6Q2Rhq'
# dpx = dropbox.dropbox.Dropbox(simonbiggs_electroninserts_accesstoken)
# with open(data_filename, 'rb') as file:
#     dpx.files_upload(file, "/{}".format(data_filename))
# with open(details_filename, 'rb') as file:
#     dpx.files_upload(file, "/{}".format(details_filename))


Out[6]:
'20160805161358_details.yaml'

Once your csv has been created it can be loaded into a pandas DataFrame as such:


In [7]:
data = pd.read_csv(data_filename)
data


Out[7]:
Label Width (cm @ 100SSD) Length (cm @ 100SSD) Energy (MeV) Applicator (cm) SSD (cm) Insert factor (dose insert / dose open)
0 Simon 3cm circle 3.15 3.16 12 10 100 0.9294
1 Simon 3x5cm oval 3.16 5.25 12 10 100 0.9346
2 Simon 3x13cm oval 3.17 13.64 12 10 100 0.9533
3 Simon 3x6.5cm oval 3.17 6.83 12 10 100 0.9488
4 Simon 3x9cm oval 3.17 9.43 12 10 100 0.9488
5 P4 3.55 7.70 12 10 100 0.9443
6 Simon #57 cutout 3.66 5.04 12 10 100 0.9434
7 Simon #112 cutout 3.71 4.36 12 10 100 0.9488
8 Simon 4cm circle 4.20 4.21 12 10 100 0.9560
9 Simon 4x10cm oval 4.21 10.51 12 10 100 0.9709
10 Simon 4x13cm oval 4.21 13.65 12 10 100 0.9756
11 Simon 4x6.5cm oval 4.21 6.82 12 10 100 0.9606
12 Simon 4x8cm oval 4.21 8.41 12 10 100 0.9709
13 Simon #20 cutout 4.38 5.47 12 10 100 0.9634
14 P10 4.48 7.29 12 10 100 0.9606
15 Simon #14 cutout 4.59 5.67 12 10 100 0.9588
16 Simon #3 cutout 4.59 6.54 12 10 100 0.9681
17 Simon #38 cutout 4.67 6.28 12 10 100 0.9737
18 Simon #22 cutout 5.21 11.40 12 10 100 0.9881
19 Simon 5cm circle 5.25 5.26 12 10 100 0.9709
20 Simon 5x10cm oval 5.26 10.52 12 10 100 0.9881
21 Simon 5x13cm oval 5.26 13.66 12 10 100 0.9872
22 Simon 5x8cm oval 5.26 8.41 12 10 100 0.9833
23 Simon #104 cutout 5.34 9.64 12 10 100 0.9930
24 P40 5.43 11.02 12 10 100 0.9872
25 Simon #19 cutout 5.72 11.60 12 10 100 0.9990
26 Simon #83 cutout 5.86 8.62 12 10 100 0.9891
27 Simon #58 cutout 6.00 7.98 12 10 100 0.9911
28 P3 6.04 9.22 12 10 100 0.9990
29 Simon #33 cutout 6.08 6.64 12 10 100 0.9930
... ... ... ... ... ... ... ...
118 P37_2 7.29 10.10 6 14 100 1.0070
119 P20 8.60 9.24 6 14 100 1.0060
120 P38_3 8.84 15.52 6 14 100 1.0030
121 P16 9.05 11.99 6 14 100 1.0111
122 P35_1 9.28 10.58 6 14 100 1.0091
123 P23 9.87 13.16 6 14 100 1.0050
124 P26 6.68 10.71 9 14 100 1.0030
125 P14_2 7.03 12.47 9 14 100 1.0173
126 P34_1 7.66 11.25 9 14 100 1.0060
127 P18 8.60 10.32 9 14 100 1.0101
128 P14_1 8.61 12.03 9 14 100 1.0163
129 P31_2 10.65 17.74 18 20 100 1.0142
130 P60 18.48 20.89 6 20 100 1.0040
131 P41 7.85 24.61 9 20 100 1.0111
132 P32 9.30 22.70 9 20 100 1.0111
133 P51 10.00 28.65 15 25 100 1.0142
134 P49 2.69 4.21 6 6 100 0.8961
135 P43 2.80 2.90 6 6 100 0.8850
136 P48 3.31 6.08 6 6 100 0.9690
137 P47 3.39 3.40 6 6 100 0.9083
138 P35_3 3.48 4.78 6 6 100 0.9390
139 Standard 4cm circle P63 4.00 4.00 6 6 100 0.9425
140 P59 4.10 5.89 6 6 100 0.9814
141 Standard 5cm circle P29 5.00 5.00 6 6 100 0.9891
142 P30 4.12 5.22 9 6 100 0.9597
143 P2 4.43 5.97 9 6 100 0.9728
144 P52 4.89 5.60 9 6 100 0.9990
145 Appears to be a standard 6cm P58 6.00 6.00 9 6 100 1.0020
146 P64 8.96 13.21 9 14 100 1.0121
147 P65 parameterised by hand 8.40 10.70 15 14 100 1.0030

148 rows × 7 columns

Singling out a single energy, applicator, ssd is as simple as the following:


In [8]:
energy = 6
applicator = 10
ssd = 100

reference = (
    (data['Energy (MeV)'] == energy) &
    (data['Applicator (cm)'] == applicator) &
    (data['SSD (cm)'] == ssd)
)

data[reference]


Out[8]:
Label Width (cm @ 100SSD) Length (cm @ 100SSD) Energy (MeV) Applicator (cm) SSD (cm) Insert factor (dose insert / dose open)
75 P62 3.99 6.51 6 10 100 0.9643
76 P50 4.10 5.99 6 10 100 0.9662
77 Simon 5cm_6MeV 4.99 5.00 6 10 100 0.9766
78 Simon 5.3x12.5cm_6MeV 5.26 12.45 6 10 100 0.9960
79 P7 5.69 7.58 6 10 100 0.9950
80 Appears to be a standard 6cm P5_1 6.00 6.00 6 10 100 0.9887
81 P9_1 5.79 7.20 6 10 100 0.9852
82 Simon 6.1cm_6MeV 6.09 6.10 6 10 100 0.9901
83 P24 6.47 8.25 6 10 100 0.9950
84 Simon 6.7x12cm_6MeV 6.76 12.00 6 10 100 0.9980
85 Simon 7.25cm_6MeV 7.23 7.26 6 10 100 1.0070
86 P35_2 7.43 10.30 6 10 100 0.9940
87 Simon 8.3cm_6MeV 8.28 8.30 6 10 100 1.0060
88 P6 8.50 10.73 6 10 100 0.9990
89 Simon 8.5x10.9cm_6MeV 8.50 10.85 6 10 100 1.0030
90 Simon 9.5cm_6MeV 9.49 9.50 6 10 100 1.0050

It is also possible to test if a given combination has sufficient data:


In [9]:
number_of_data = len(data[reference])
print("Number of data = {}".format(number_of_data))

number_of_data >= 8


Number of data = 16
Out[9]:
True

Displaying model report given applicator / energy / ssd combination


In [10]:
reset_output()
output_notebook()

energy = 6
applicator = 10
ssd = 100

reference = (
    (data['Energy (MeV)'] == energy) &
    (data['Applicator (cm)'] == applicator) &
    (data['SSD (cm)'] == ssd)
)

input_dataframe = data[reference]

label = np.array(input_dataframe['Label']).astype(str)
width_data = np.array(input_dataframe['Width (cm @ 100SSD)']).astype(float)
length_data = np.array(input_dataframe['Length (cm @ 100SSD)']).astype(float)
factor_data = np.array(input_dataframe['Insert factor (dose insert / dose open)']).astype(float)
ratio_perim_area_data = convert2_ratio_perim_area(width_data, length_data)

figure = interactive(
    width_data, length_data, ratio_perim_area_data, factor_data, label)
show(figure)


Loading BokehJS ...
Out[10]:

<Bokeh Notebook handle for In[10]>


In [11]:
reset_output()
output_notebook()
# output_file("test.html", title="test")

energy = 9
applicator = 6
ssd = 100

reference = (
    (data['Energy (MeV)'] == energy) &
    (data['Applicator (cm)'] == applicator) &
    (data['SSD (cm)'] == ssd)
)

input_dataframe = data[reference]

label = np.array(input_dataframe['Label']).astype(str)
width_data = np.array(input_dataframe['Width (cm @ 100SSD)']).astype(float)
length_data = np.array(input_dataframe['Length (cm @ 100SSD)']).astype(float)
factor_data = np.array(input_dataframe['Insert factor (dose insert / dose open)']).astype(float)

figure = fallback_scatter(width_data, length_data, factor_data, label)

show(figure)


Loading BokehJS ...
Out[11]:

<Bokeh Notebook handle for In[11]>

Creating reports


In [12]:
energy_array = np.unique(data['Energy (MeV)'])
applicator_array = np.unique(data['Applicator (cm)'])
ssd_array = np.unique(data['SSD (cm)'])

print("Iterate over the following scenarios:")
print("Energy = {}".format(energy_array))
print("Applicator = {}".format(applicator_array))
print("SSD = {}".format(ssd_array))


Iterate over the following scenarios:
Energy = [ 6  9 12 15 18]
Applicator = [ 6 10 14 20 25]
SSD = [100]

In [13]:
# reset_output()
# output_notebook()

for energy in energy_array:
    for applicator in applicator_array:
        for ssd in ssd_array:
            
            reference = (
                (data['Energy (MeV)'] == energy) &
                (data['Applicator (cm)'] == applicator) &
                (data['SSD (cm)'] == ssd)
            )
            
            input_dataframe = data[reference]
            label = np.array(input_dataframe['Label']).astype(str)
            width_data = np.array(
                input_dataframe['Width (cm @ 100SSD)']).astype(float)
            length_data = np.array(
                input_dataframe['Length (cm @ 100SSD)']).astype(float)
            factor_data = np.array(
                input_dataframe['Insert factor (dose insert / dose open)']).astype(float)
            
            number_of_data = len(input_dataframe)
            filename = "{}_{}energy_{}applicator_{}ssd_{}data.html".format(
                timestamp, str(energy).zfill(2), str(applicator).zfill(2), 
                str(ssd).zfill(3), str(number_of_data).zfill(2))
            title = "{}MeV | {}App | {}SSD".format(
                energy, applicator, ssd)
            
            reset_output()
            output_file(filename, title=title)
            
            if number_of_data >= 8:
                ratio_perim_area_data = convert2_ratio_perim_area(width_data, length_data)

                figure = interactive(
                    width_data, length_data, ratio_perim_area_data, factor_data, label)
            else:
                figure = fallback_scatter(width_data, length_data, factor_data, label)
                
            save(figure)

In [14]:
created_reports = glob("{}*.html".format(timestamp))
zip_filename = '{}_reports.zip'.format(timestamp)

with zipfile.ZipFile(zip_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
    for file in created_reports:
        zipf.write(file)
    
    zipf.write(details_filename)
    zipf.write(data_filename)

display(Markdown("[To download reports: `Right click me > Save link as...`]({}_reports.zip)".format(timestamp)))




Copyright © 2016 Simon Biggs

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with this program. If not, see http://www.gnu.org/licenses/.