#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
test_dvh
----------------------------------

Tests for `dvh` module.
"""

import json
import unittest2 as unittest
import numpy as np
from dvh import DVH, monotonic_increasing, monotonic_decreasing


class TestDvh(unittest.TestCase):

    def setUp(self):

        self.test_diff_vols = [0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 2, 1, 0, 0, 0, 0, 0, 10, 20, 30, 40, 50, 60, 70, 60, 50, 40, 30, 20, 10, 0, 0]
        self.test_cum_vols = [ 518,  518,  518,  518,  518,  518,  518,  518,  518,  517,  515,  512,  508,  503,  497,  493,  491,  490,  490,  490,  490,  490,  490,  480,  460,  430,  390,  340,  280,  210,  150,  100,   60,   30,   10,    0,  0.]
        self.min_dose = 80
        self.max_dose = 340
        self.mean_dose = 285
        self.test_doses = np.arange(0, 370, 10)



        self.test_structs = {
            "Ant Scalene" : {
                "doses": [0, 395, 405, 415, 425, 435, 445, 465, 475, 485, 495, 505, 515, 525, 535, 545, 555, 565, 585, 595, 605, 615, 625, 635, 645, 655, 665, 675, 685, 715, 725, 735, 755, 765, 775, 795, 805, 815, 825, 835, 845, 855, 865, 875, 885, 895, 905, 915, 955, 965, 975, 985, 995, 1005, 1015, 1025, 1035, 1045, 1055, 1065, 1075, 1085, 1095, 1105, 1115, 1125, 1135, 1145, 1155, 1165, 1175, 1195, 1215, 1225, 1235, 1245, 1255, 1265, 1285, 1295, 1305, 1315, 1325, 1335, 1355, 1375, 1385, 1395, 1405, 1415, 1425, 1435, 1445, 1455, 1465, 1475, 1485, 1495, 1505, 1525, 1535, 1545, 1555, 1565, 1575, 1585, 1595, 1605, 1615, 1625, 1635, 1645, 1655, 1665, 1675, 1685, 1695, 1705, 1715, 1725, 1735, 1745, 1755, 1765, 1775, 1785, 1795, 1805, 1825, 1835, 1845, 1855, 1865, 1875, 1885, 1895, 1905, 1925, 1935, 1945, 1955, 1965, 1975, 1985, 1995, 2005, 2015, 2025, 2035, 2085, 2095, 2105, 2115, 2125, 2135, 2145, 2155, 2165, 2175, 2205, 2215, 2225, 2235, 2275, 2285, 2295, 2305, 2315, 2335, 2355, 2385, 2405, 2415, 2425, 2435, 2445, 2455, 2465, 2485, 2505, 2515, 2525, 2535, 2545, 2555, 2565, 2575, 2585, 2595, 2605, 2625, 2635, 2645, 2655, 2665, 2675, 2685, 2695, 2705, 2715, 2735, 2745, 2765, 2775, 2785, 2795, 2805, 2815, 2825, 2835, 2845, 2855, 2865, 2875, 2885, 2895, 2905, 2915, 2925, 2935, 2945, 2955, 2965, 2975, 2985, 2995, 3005, 3025, 3035, 3045, 3055, 3065, 3075, 3085, 3095, 3115, 3125, 3135, 3145, 3155, 3165, 3175, 3185, 3195, 3205, 3215, 3225, 3235, 3245, 3255, 3265, 3275, 3285, 3295, 3305, 3315, 3325, 3335, 3345, 3355, 3365, 3375, 3385, 3395, 3405, 3415, 3425, 3435, 3445, 3455, 3465, 3475, 3485, 3495, 3505, 3515, 3525, 3535, 3545, 3555, 3565, 3575, 3585, 3595, 3605, 3615, 3625, 3645, 3655, 3665, 3675, 3685, 3695, 3705, 3715, 3725, 3735, 3745, 3755, 3765, 3775, 3785, 3795, 3815, 3825, 3835, 3845, 3855, 3865, 3875, 3885, 3895, 3905, 3925, 3935, 3955, 3965, 3985, 3995, 4005, 4015, 4025, 4035, 4045, 4055, 4065, 4075, 4085, 4095, 4105, 4115, 4125, 4135, 4145, 4155, 4165, 4175, 4195, 4205, 4215, 4225, 4235, 4245, 4255, 4265, 4275, 4285, 4295, 4305, 4325, 4335, 4355, 4365, 4375, 4385, 4405, 4415, 4425, 4445, 4465, 4475, 4495, 4505, 4515, 4525, 4535, 4545, 4595, 4615, 4625, 4635, 4645, 4655, 4665, 4675, 4685, 4695, 4705, 4715, 4725, 4735, 4745, 4755, 4765, 4775, 4785, 4795, 4805, 4815, 4825, 4835, 4845, 4855, 4865, 4875, 4885, 4895, 4905, 4915, 4925, 4935, 4945, 4955, 4965, 4975, 4985, 4995, 5005, 5015, 5025, 5035, 5045, 5055, 5065, 5075, 5085, 5095, 5105, 5115, 5125, 5135, 5145, 5155, 5175, 5185, 5195, 5205, 5215, 5225, 5235, 5245, 5255, 5265, 5275, 5285, 5295, 5305, 5315, 5325, 5335, 5345, 5355, 5365, 5375, 5385, 5405, 5415, 5425, 5435, 5445, 5455, 5465, 5475, 5485, 5495, 5505, 5515, 5525, 5535, 5545, 5555, 5565, 5575, 5585, 5595, 5605, 5615, 5625, 5635, 5645, 5655, 5665, 5675, 5685, 5695, 5705, 5715, 5725, 5735, 5745, 5755, 5765, 5775, 5785, 5805, 5815, 5825, 6955, 6960],
                "volumes": [8.155, 8.155, 8.132, 8.102, 8.058, 8.02, 7.969, 7.855, 7.793, 7.738, 7.69, 7.641, 7.604, 7.572, 7.55, 7.527, 7.503, 7.485, 7.427, 7.411, 7.393, 7.38, 7.363, 7.341, 7.32, 7.292, 7.273, 7.255, 7.234, 7.156, 7.125, 7.102, 7.06, 7.041, 7.021, 6.993, 6.984, 6.971, 6.962, 6.957, 6.949, 6.94, 6.926, 6.919, 6.911, 6.899, 6.891, 6.882, 6.854, 6.843, 6.836, 6.83, 6.819, 6.807, 6.796, 6.784, 6.773, 6.761, 6.755, 6.746, 6.738, 6.727, 6.72, 6.714, 6.706, 6.699, 6.693, 6.684, 6.676, 6.67, 6.659, 6.643, 6.623, 6.614, 6.607, 6.596, 6.59, 6.585, 6.565, 6.561, 6.548, 6.544, 6.537, 6.527, 6.513, 6.501, 6.494, 6.489, 6.485, 6.479, 6.474, 6.471, 6.465, 6.462, 6.454, 6.448, 6.444, 6.436, 6.431, 6.419, 6.415, 6.407, 6.4, 6.396, 6.388, 6.381, 6.372, 6.369, 6.36, 6.357, 6.346, 6.341, 6.332, 6.33, 6.324, 6.321, 6.315, 6.312, 6.308, 6.303, 6.301, 6.296, 6.293, 6.288, 6.284, 6.279, 6.273, 6.265, 6.255, 6.248, 6.244, 6.238, 6.23, 6.228, 6.22, 6.215, 6.209, 6.195, 6.19, 6.181, 6.175, 6.168, 6.163, 6.155, 6.151, 6.144, 6.139, 6.132, 6.127, 6.107, 6.102, 6.099, 6.092, 6.088, 6.083, 6.08, 6.075, 6.065, 6.061, 6.046, 6.04, 6.031, 6.027, 6.003, 5.994, 5.99, 5.984, 5.979, 5.965, 5.957, 5.939, 5.931, 5.925, 5.921, 5.918, 5.911, 5.907, 5.901, 5.893, 5.883, 5.879, 5.872, 5.868, 5.865, 5.855, 5.85, 5.846, 5.838, 5.833, 5.829, 5.813, 5.809, 5.803, 5.798, 5.79, 5.785, 5.778, 5.77, 5.767, 5.761, 5.747, 5.746, 5.734, 5.73, 5.724, 5.719, 5.716, 5.708, 5.702, 5.7, 5.695, 5.689, 5.684, 5.68, 5.675, 5.671, 5.662, 5.656, 5.653, 5.647, 5.639, 5.634, 5.63, 5.622, 5.619, 5.612, 5.603, 5.595, 5.589, 5.58, 5.576, 5.57, 5.566, 5.561, 5.557, 5.551, 5.545, 5.54, 5.536, 5.528, 5.525, 5.519, 5.514, 5.508, 5.5, 5.495, 5.489, 5.481, 5.476, 5.467, 5.463, 5.45, 5.446, 5.438, 5.432, 5.425, 5.415, 5.409, 5.401, 5.396, 5.388, 5.383, 5.375, 5.37, 5.366, 5.364, 5.358, 5.356, 5.352, 5.347, 5.345, 5.338, 5.332, 5.327, 5.324, 5.313, 5.309, 5.303, 5.295, 5.291, 5.274, 5.267, 5.257, 5.249, 5.242, 5.234, 5.227, 5.215, 5.204, 5.197, 5.192, 5.185, 5.181, 5.174, 5.168, 5.163, 5.157, 5.152, 5.144, 5.135, 5.128, 5.118, 5.112, 5.094, 5.08, 5.065, 5.056, 5.051, 5.045, 5.042, 5.034, 5.029, 5.019, 5.013, 5.007, 4.997, 4.994, 4.986, 4.978, 4.972, 4.963, 4.956, 4.936, 4.919, 4.911, 4.896, 4.883, 4.873, 4.866, 4.856, 4.852, 4.846, 4.844, 4.84, 4.838, 4.833, 4.83, 4.826, 4.82, 4.817, 4.811, 4.809, 4.801, 4.796, 4.786, 4.78, 4.766, 4.745, 4.723, 4.695, 4.687, 4.669, 4.663, 4.647, 4.639, 4.621, 4.613, 4.606, 4.594, 4.58, 4.575, 4.559, 4.55, 4.544, 4.54, 4.531, 4.525, 4.48, 4.458, 4.445, 4.431, 4.412, 4.396, 4.381, 4.361, 4.345, 4.335, 4.317, 4.291, 4.274, 4.252, 4.227, 4.198, 4.173, 4.142, 4.12, 4.093, 4.054, 4.025, 3.997, 3.956, 3.918, 3.879, 3.835, 3.775, 3.718, 3.662, 3.6, 3.541, 3.48, 3.418, 3.376, 3.324, 3.274, 3.221, 3.175, 3.142, 3.1, 3.052, 3.01, 2.96, 2.918, 2.872, 2.835, 2.791, 2.75, 2.712, 2.673, 2.639, 2.603, 2.548, 2.506, 2.455, 2.335, 2.279, 2.209, 2.141, 2.07, 1.994, 1.927, 1.846, 1.766, 1.689, 1.632, 1.565, 1.502, 1.434, 1.375, 1.318, 1.254, 1.204, 1.151, 1.097, 1.056, 1.005, 0.915, 0.868, 0.832, 0.792, 0.748, 0.711, 0.675, 0.638, 0.599, 0.563, 0.518, 0.492, 0.468, 0.436, 0.39, 0.359, 0.341, 0.319, 0.288, 0.266, 0.235, 0.211, 0.197, 0.181, 0.156, 0.137, 0.12, 0.106, 0.087, 0.075, 0.057, 0.048, 0.037, 0.027, 0.019, 0.014, 0.012, 0.008, 0.003, 0.001, 0.001, 0, 0, 0],
                "monaco_dvh_mean_dose": 3752.2,
                "monaco_dvh_max_dose":5810.4,
                "monaco_dvh_min_dose":391.9,
                "monaco_dvh_volume": 8.155

            },
            "PTV50": {
                "doses":[0, 3555, 3585, 3595, 3605, 3615, 3625, 3635, 3655, 3665, 3675, 3685, 3705, 3715, 3725, 3735, 3745, 3755, 3775, 3785, 3795, 3805, 3815, 3825, 3835, 3855, 3875, 3885, 3895, 3905, 3915, 3925, 3945, 3955, 3965, 3975, 3985, 3995, 4005, 4015, 4025, 4045, 4055, 4065, 4075, 4085, 4095, 4105, 4115, 4125, 4135, 4145, 4155, 4165, 4175, 4185, 4205, 4215, 4225, 4235, 4245, 4255, 4265, 4275, 4285, 4295, 4305, 4315, 4325, 4335, 4345, 4355, 4365, 4375, 4385, 4395, 4405, 4415, 4425, 4435, 4445, 4455, 4465, 4475, 4485, 4495, 4505, 4515, 4525, 4535, 4545, 4555, 4565, 4575, 4585, 4595, 4605, 4615, 4625, 4635, 4645, 4655, 4665, 4675, 4685, 4695, 4705, 4715, 4725, 4735, 4745, 4755, 4765, 4775, 4785, 4795, 4805, 4815, 4825, 4835, 4845, 4855, 4865, 4875, 4885, 4895, 4905, 4915, 4925, 4935, 4945, 4955, 4965, 4975, 4985, 4995, 5005, 5015, 5025, 5035, 5045, 5055, 5065, 5075, 5085, 5095, 5105, 5115, 5125, 5135, 5145, 5155, 5165, 5175, 5185, 5195, 5205, 5215, 5225, 5235, 5245, 5255, 5265, 5275, 5285, 5295, 5305, 5315, 5325, 5335, 5345, 5355, 5365, 5375, 5385, 5395, 5405, 5415, 5425, 5435, 5445, 5455, 5465, 5475, 5485, 5495, 5505, 5515, 5525, 5535, 5545, 5555, 5565, 5575, 5585, 5595, 5605, 5615, 5625, 5635, 5645, 5655, 5665, 5675, 5685, 5695, 5705, 5715, 5725, 5735, 5745, 5755, 5765, 5775, 5785, 5795, 5805, 5815, 5825, 5835, 5845, 5855, 5865, 5875, 5885, 5895, 5905, 5915, 5935, 5945, 5955, 5965, 5975, 5985, 5995, 6005, 6015, 6025, 6035, 6045, 6055, 6065, 6075, 6085, 6095, 6105, 6115, 6125, 6135, 6145, 6155, 6165, 6175, 6185, 6195, 6205, 6215, 6225, 6235, 6245, 6255, 6275, 6285, 6295, 6305, 6315, 6325, 6335, 6345, 6355, 6365, 6375, 6385, 6395, 6405, 6415, 6425, 6435, 6445, 6455, 6465, 6475, 6495, 6505, 6515, 6525, 6535, 6545, 6555, 6565, 6575, 6585, 6595, 6615, 6625, 6635, 6645, 6655, 6665, 6675, 6685, 6705, 6715, 6725, 6735, 6745, 6755, 6765, 6775, 6785, 6795, 6805, 6835, 6845, 6855, 6865, 6875, 6885, 6895, 6915, 6925, 6955, 6960],
                "volumes":[503.55, 503.55, 503.547, 503.547, 503.546, 503.546, 503.544, 503.543, 503.539, 503.538, 503.536, 503.535, 503.531, 503.527, 503.524, 503.524, 503.519, 503.516, 503.506, 503.504, 503.501, 503.496, 503.494, 503.488, 503.483, 503.475, 503.463, 503.456, 503.447, 503.444, 503.437, 503.431, 503.415, 503.403, 503.396, 503.39, 503.382, 503.372, 503.361, 503.351, 503.339, 503.313, 503.297, 503.28, 503.268, 503.252, 503.232, 503.219, 503.202, 503.182, 503.161, 503.142, 503.122, 503.095, 503.078, 503.055, 502.993, 502.965, 502.931, 502.89, 502.853, 502.824, 502.786, 502.742, 502.705, 502.658, 502.606, 502.549, 502.507, 502.47, 502.426, 502.364, 502.296, 502.215, 502.123, 502.021, 501.926, 501.812, 501.693, 501.572, 501.409, 501.259, 501.071, 500.901, 500.701, 500.509, 500.289, 500.082, 499.841, 499.631, 499.414, 499.155, 498.892, 498.602, 498.303, 498.013, 497.719, 497.379, 497.034, 496.671, 496.275, 495.834, 495.359, 494.892, 494.405, 493.9, 493.358, 492.778, 492.147, 491.507, 490.822, 490.076, 489.288, 488.457, 487.645, 486.765, 485.826, 484.908, 483.894, 482.79, 481.635, 480.475, 479.222, 477.921, 476.512, 475.076, 473.488, 471.788, 470, 468.173, 466.216, 464.019, 461.764, 459.476, 456.935, 454.375, 451.576, 448.685, 445.574, 442.376, 438.931, 435.272, 431.381, 427.266, 422.727, 417.732, 412.308, 406.508, 399.991, 393.073, 385.506, 377.4, 368.671, 359.176, 349.297, 339.141, 328.753, 317.937, 306.855, 295.682, 284.517, 273.104, 261.631, 250.185, 238.529, 227.263, 215.981, 205.16, 194.649, 184.384, 174.428, 164.929, 155.956, 147.426, 139.562, 132.239, 125.344, 118.648, 112.3, 106.306, 100.578, 95.438, 90.599, 85.996, 81.76, 77.718, 73.767, 70.076, 66.49, 62.922, 59.532, 56.333, 53.35, 50.513, 47.901, 45.409, 43.069, 40.826, 38.709, 36.767, 34.888, 33.286, 31.767, 30.349, 29.07, 27.846, 26.646, 25.562, 24.474, 23.416, 22.406, 21.452, 20.429, 19.51, 18.606, 17.767, 16.964, 16.129, 15.335, 14.598, 13.852, 13.165, 12.461, 11.826, 11.222, 10.7, 10.134, 9.664, 8.738, 8.28, 7.828, 7.411, 7.026, 6.634, 6.272, 5.954, 5.658, 5.351, 5.051, 4.745, 4.463, 4.212, 3.977, 3.756, 3.523, 3.311, 3.13, 2.963, 2.815, 2.692, 2.58, 2.467, 2.359, 2.269, 2.182, 2.09, 2.008, 1.925, 1.834, 1.742, 1.655, 1.505, 1.426, 1.36, 1.284, 1.221, 1.168, 1.101, 1.028, 0.964, 0.918, 0.879, 0.841, 0.795, 0.762, 0.727, 0.691, 0.665, 0.634, 0.614, 0.587, 0.557, 0.517, 0.496, 0.469, 0.449, 0.42, 0.406, 0.379, 0.363, 0.351, 0.327, 0.308, 0.272, 0.258, 0.236, 0.216, 0.192, 0.173, 0.159, 0.142, 0.114, 0.103, 0.097, 0.085, 0.07, 0.061, 0.057, 0.055, 0.048, 0.038, 0.031, 0.019, 0.017, 0.012, 0.01, 0.01, 0.006, 0.005, 0.005, 0.002, 0.002, 0],
                "monaco_dvh_mean_dose": 5277.2,
                "monaco_dvh_max_dose": 6959.8,
                "monaco_dvh_min_dose": 3552.2,
                "monaco_dvh_volume": 503.55,
            },
            "prv cord": {

                "doses": [0, 5, 15, 25, 35, 45, 55, 65, 75, 85, 95, 105, 115, 125, 135, 145, 155, 165, 175, 185, 195, 205, 215, 225, 235, 245, 255, 265, 275, 285, 295, 305, 315, 325, 335, 345, 355, 365, 375, 385, 395, 405, 415, 425, 435, 445, 455, 465, 475, 485, 495, 505, 515, 525, 535, 545, 555, 565, 575, 585, 595, 605, 615, 625, 635, 645, 655, 665, 675, 685, 695, 705, 715, 725, 735, 745, 755, 765, 775, 785, 795, 805, 815, 825, 835, 845, 855, 865, 875, 885, 895, 905, 915, 925, 935, 945, 955, 965, 975, 985, 995, 1005, 1015, 1025, 1035, 1045, 1055, 1065, 1075, 1085, 1095, 1105, 1115, 1125, 1135, 1145, 1155, 1165, 1175, 1185, 1195, 1205, 1215, 1225, 1235, 1245, 1255, 1265, 1275, 1285, 1295, 1305, 1315, 1325, 1335, 1345, 1355, 1365, 1375, 1385, 1395, 1405, 1415, 1425, 1435, 1445, 1455, 1465, 1475, 1485, 1495, 1505, 1515, 1525, 1535, 1545, 1555, 1565, 1575, 1585, 1595, 1605, 1625, 1635, 1645, 1655, 1665, 1675, 1685, 1695, 1705, 1715, 1725, 1735, 1745, 1755, 1765, 1775, 1785, 1795, 1805, 1815, 1825, 1835, 1845, 1855, 1865, 1875, 1885, 1895, 1905, 1915, 1925, 1935, 1945, 1955, 1965, 1975, 1985, 1995, 2005, 2015, 2025, 2035, 2045, 2065, 2075, 2085, 2095, 2105, 2115, 2125, 2135, 2145, 2155, 2165, 2175, 2185, 2195, 2205, 2215, 2225, 2235, 2245, 2255, 2265, 2275, 2285, 2295, 2305, 2315, 2325, 2335, 2345, 2355, 2365, 2375, 2385, 2395, 2405, 2425, 2435, 2445, 2465, 2475, 2485, 2495, 2505, 2515, 2525, 2535, 2545, 2555, 2565, 2575, 2585, 2595, 2605, 2615, 2625, 2635, 2655, 2665, 2685, 2695, 2705, 2715, 2725, 2735, 2745, 2755, 2765, 2775, 2785, 2795, 2805, 2835, 2845, 2855, 2865, 2885, 2895, 6955, 6960],
                "volumes" : [202.215, 202.215, 185.281, 178.426, 171.883, 166.421, 162.144, 157.958, 154.472, 151.367, 148.431, 145.753, 143.439, 141.707, 140.066, 138.441, 136.694, 135.114, 133.489, 131.856, 129.909, 127.67, 124.556, 121.016, 117.495, 113.781, 110.265, 107.293, 104.206, 101.475, 98.956, 96.835, 95.416, 94.425, 93.538, 92.733, 91.921, 91.097, 90.15, 88.896, 87.359, 85.697, 83.861, 81.868, 79.835, 77.708, 75.325, 72.962, 70.615, 68.584, 66.794, 65.322, 63.94, 62.758, 61.605, 60.413, 59.285, 58.128, 57.042, 55.941, 55, 54.143, 53.374, 52.683, 51.949, 51.262, 50.66, 50.156, 49.664, 49.189, 48.707, 48.205, 47.698, 47.239, 46.783, 46.353, 45.919, 45.523, 45.088, 44.702, 44.364, 44.045, 43.729, 43.462, 43.205, 42.962, 42.736, 42.508, 42.301, 42.107, 41.9, 41.728, 41.535, 41.366, 41.178, 41.005, 40.827, 40.621, 40.423, 40.224, 40.008, 39.794, 39.567, 39.353, 39.114, 38.882, 38.646, 38.408, 38.118, 37.882, 37.568, 37.307, 37.045, 36.732, 36.432, 36.127, 35.824, 35.502, 35.141, 34.793, 34.446, 34.062, 33.688, 33.277, 32.875, 32.393, 31.967, 31.485, 31.006, 30.481, 29.97, 29.379, 28.812, 28.202, 27.566, 26.877, 26.193, 25.525, 24.791, 24.072, 23.345, 22.586, 21.809, 20.975, 20.188, 19.355, 18.582, 17.762, 16.988, 16.176, 15.425, 14.745, 14.056, 13.373, 12.746, 12.11, 11.542, 10.978, 10.418, 9.902, 9.441, 8.991, 8.191, 7.822, 7.482, 7.169, 6.887, 6.598, 6.352, 6.087, 5.867, 5.65, 5.434, 5.225, 5.032, 4.862, 4.67, 4.501, 4.325, 4.172, 4.016, 3.874, 3.728, 3.602, 3.455, 3.322, 3.198, 3.082, 2.972, 2.861, 2.747, 2.644, 2.558, 2.476, 2.383, 2.298, 2.199, 2.138, 2.061, 1.989, 1.928, 1.852, 1.791, 1.734, 1.669, 1.557, 1.498, 1.45, 1.398, 1.347, 1.29, 1.251, 1.2, 1.163, 1.12, 1.072, 1.036, 1.001, 0.959, 0.921, 0.889, 0.847, 0.815, 0.782, 0.75, 0.724, 0.691, 0.666, 0.637, 0.61, 0.582, 0.553, 0.525, 0.502, 0.477, 0.456, 0.426, 0.409, 0.388, 0.372, 0.33, 0.311, 0.29, 0.256, 0.243, 0.221, 0.206, 0.197, 0.181, 0.168, 0.158, 0.143, 0.132, 0.129, 0.12, 0.112, 0.1, 0.093, 0.082, 0.072, 0.069, 0.059, 0.05, 0.04, 0.038, 0.03, 0.026, 0.025, 0.022, 0.018, 0.016, 0.013, 0.013, 0.012, 0.012, 0.009, 0.006, 0.006, 0.003, 0.002, 0.002, 0, 0, 0],
                "monaco_dvh_mean_dose": 496.7,
                "monaco_dvh_max_dose": 2889.2,
                "monaco_dvh_min_dose": 0,
                "monaco_dvh_volume": 202.215,
            }
        }

    def test_realistic_mean_dose(self):
        """test mean dose within 1cGy"""

        for struct, data in self.test_structs.items():
            dvh = DVH(data["doses"], data["volumes"])
            diff = dvh.mean_dose - data["monaco_dvh_mean_dose"]
            self.assertLessEqual(abs(diff), 1)

    def test_realistic_min_dose(self):
        """test min dose within 1cGy"""

        # min and max dose can only really hope to be within half a bin width

        for struct, data in self.test_structs.items():
            dvh = DVH(data["doses"], data["volumes"])
            diff = dvh.min_dose - data["monaco_dvh_min_dose"]
            self.assertLessEqual(abs(diff), 5.)

    def test_realistic_max_dose(self):
        """test max dose within 5cGy"""

        # min and max dose can only really hope to be within half a bin width

        for struct, data in self.test_structs.items():
            dvh = DVH(data["doses"], data["volumes"])
            diff = dvh.max_dose - data["monaco_dvh_max_dose"]
            self.assertLessEqual(abs(diff), 5.)

    def test_missing_doses(self):
        with self.assertRaises(ValueError):
            dvh = DVH(volumes=[1,2])

    def test_missing_volumes(self):
        with self.assertRaises(ValueError):
            dvh = DVH(doses=[1,2])

    def test_no_zero_dose_dif(self):
        doses = [1, 2, 3]
        volumes = [30, 0, 10]
        dvh = DVH(doses, volumes)
        self.assertEqual(dvh.mean_dose, 1.5)

    def test_no_zero_dose_cum(self):
        doses = [1, 2, 3, 4]
        volumes = [30, 30, 10, 5]
        dvh = DVH(doses, volumes)
        self.assertEqual(dvh.mean_dose, (5.*4. + 5*3 +20*2)/(5. + 5 + 20))

    def test_dmax(self):
        dvh = DVH(self.test_doses, self.test_diff_vols)
        self.assertEqual(dvh.max_dose, self.max_dose)

    def test_dmin(self):
        dvh = DVH(self.test_doses, self.test_diff_vols)
        self.assertEqual(dvh.min_dose, self.min_dose)

    def test_dmean(self):
        """TODO: Develop real worlds tests"""
        doses = [0, 1, 2, 3]
        volumes = [10, 0, 0, 10]

        dvh = DVH(doses, volumes)
        self.assertEqual(dvh.mean_dose, 1.5)

    def test_monotonic_increasing_strict(self):
        self.assertTrue(monotonic_increasing(range(4)))
        self.assertFalse(monotonic_increasing(self.test_diff_vols))

    def test_monotonic_decreasing(self):
        self.assertFalse(monotonic_decreasing(self.test_diff_vols))
        self.assertTrue(monotonic_decreasing(list(reversed(range(4)))))

    def test_diff_converted_to_cumulative(self):
        dvh = DVH(self.test_doses, self.test_diff_vols)
        self.assertAlmostEqual(dvh.cum_volumes[0], 1)

    def test_invalid_bin_count(self):
        with self.assertRaises(ValueError):
            dvh = DVH(self.test_doses[:-1], self.test_diff_vols)

    def test_invalid_bins(self):
        with self.assertRaises(ValueError):
            dvh = DVH([1,3,1], [2,4])

    def test_cumulative_to_diff(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        dvh2 = DVH(self.test_doses, dvh.diff_volumes)
        self.assertAlmostEqual(sum(dvh2.cum_volumes - dvh.cum_volumes), 0)

    def test_dose_to_volume_fraction_0(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.dose_to_volume_fraction(0), self.max_dose)

    def test_dose_to_volume_fraction_1(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.dose_to_volume_fraction(1), self.min_dose)

    def test_dose_to_volume_fraction_mid(self):
        """ A volume fraction of 0.9999999999 should give just slightly more than min dose"""
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.dose_to_volume_fraction(0.9999999999), self.min_dose, places=4)
        self.assertGreater(dvh.dose_to_volume_fraction(0.9999999999), self.min_dose)

    def test_dose_to_volume_fraction_invalid(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        with self.assertRaises(ValueError):
            dvh.dose_to_volume_fraction(100)

    def test_volume_fraction_receiving_zero_or_more_dose(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(0), 1)

    def test_volume_fraction_receiving_more_than_max_dose(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(dvh.max_dose+1), 0)

    def test_volume_fraction_receiving_dose(self):
        doses = [0, 1, 2, 3]
        volumes = [10, 0, 0, 10]
        dvh = DVH(doses, volumes)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(dvh.mean_dose), 0.5)

    def test_to_dict(self):
        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]

        dvh = DVH(doses, volumes)

        expected = {
            'diff_volumes': [0.0, 0.0, 0.5, 0.0, 0.5, 0.0],
            'cum_volumes': [1.0, 1.0, 1.0, 0.5, 0.5, 0.0],
            'doses': [0.0, 1.0, 2.0, 3.0, 4.0, 5.0],
            'mean_dose': 3.0,
            'max_dose': 4.0,
            'min_dose': 2.0
        }
        self.assertDictEqual(expected, dvh.to_dict())

    def test_to_dict_no_diff(self):
        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]

        dvh = DVH(doses, volumes)

        expected = {
            'cum_volumes': [1.0, 1.0, 1.0, 0.5, 0.5, 0.0],
            'doses': [0.0, 1.0, 2.0, 3.0, 4.0, 5.0],
            'mean_dose': 3.0,
            'max_dose': 4.0,
            'min_dose': 2.0
        }
        self.assertDictEqual(expected, dvh.to_dict(False))

    def test_json_serialze(self):

        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]

        dvh = DVH(doses, volumes)

        expected = {
            'diff_volumes': [0.0, 0.0, 0.5, 0.0, 0.5, 0.0],
            'cum_volumes': [1.0, 1.0, 1.0, 0.5, 0.5, 0.0],
            'doses': [0.0, 1.0, 2.0, 3.0, 4.0, 5.0],
            'mean_dose': 3.0,
            'max_dose': 4.0,
            'min_dose': 2.0
        }
        self.assertDictEqual(json.loads(json.dumps(expected)), json.loads(dvh.serialize()))

    def test_json_serialze_invalid(self):

        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]

        dvh = DVH(doses, volumes)
        with self.assertRaises(TypeError):
            dvh.serialize(method="blah")


if __name__ == '__main__':
    unittest.main()

    def test_dose_to_volume_fraction_invalid(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        with self.assertRaises(ValueError):
            dvh.dose_to_volume_fraction(100)

if __name__ == '__main__':
    unittest.main()

8ba8f4a00b40aca62e0d5f9f71cd7c6fd35ec053
<mask token>


class TestDvh(unittest.TestCase):
    <mask token>

    def test_realistic_mean_dose(self):
        """test mean dose within 1cGy"""
        for struct, data in self.test_structs.items():
            dvh = DVH(data['doses'], data['volumes'])
            diff = dvh.mean_dose - data['monaco_dvh_mean_dose']
            self.assertLessEqual(abs(diff), 1)

    def test_realistic_min_dose(self):
        """test min dose within 1cGy"""
        for struct, data in self.test_structs.items():
            dvh = DVH(data['doses'], data['volumes'])
            diff = dvh.min_dose - data['monaco_dvh_min_dose']
            self.assertLessEqual(abs(diff), 5.0)

    def test_realistic_max_dose(self):
        """test max dose within 5cGy"""
        for struct, data in self.test_structs.items():
            dvh = DVH(data['doses'], data['volumes'])
            diff = dvh.max_dose - data['monaco_dvh_max_dose']
            self.assertLessEqual(abs(diff), 5.0)
    <mask token>

    def test_missing_volumes(self):
        with self.assertRaises(ValueError):
            dvh = DVH(doses=[1, 2])
    <mask token>

    def test_no_zero_dose_cum(self):
        doses = [1, 2, 3, 4]
        volumes = [30, 30, 10, 5]
        dvh = DVH(doses, volumes)
        self.assertEqual(dvh.mean_dose, (5.0 * 4.0 + 5 * 3 + 20 * 2) / (5.0 +
            5 + 20))
    <mask token>
    <mask token>
    <mask token>
    <mask token>
    <mask token>

    def test_diff_converted_to_cumulative(self):
        dvh = DVH(self.test_doses, self.test_diff_vols)
        self.assertAlmostEqual(dvh.cum_volumes[0], 1)

    def test_invalid_bin_count(self):
        with self.assertRaises(ValueError):
            dvh = DVH(self.test_doses[:-1], self.test_diff_vols)
    <mask token>
    <mask token>

    def test_dose_to_volume_fraction_0(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.dose_to_volume_fraction(0), self.max_dose)
    <mask token>
    <mask token>

    def test_dose_to_volume_fraction_invalid(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        with self.assertRaises(ValueError):
            dvh.dose_to_volume_fraction(100)

    def test_volume_fraction_receiving_zero_or_more_dose(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(0), 1)

    def test_volume_fraction_receiving_more_than_max_dose(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(dvh.
            max_dose + 1), 0)

    def test_volume_fraction_receiving_dose(self):
        doses = [0, 1, 2, 3]
        volumes = [10, 0, 0, 10]
        dvh = DVH(doses, volumes)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(dvh.
            mean_dose), 0.5)

    def test_to_dict(self):
        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]
        dvh = DVH(doses, volumes)
        expected = {'diff_volumes': [0.0, 0.0, 0.5, 0.0, 0.5, 0.0],
            'cum_volumes': [1.0, 1.0, 1.0, 0.5, 0.5, 0.0], 'doses': [0.0, 
            1.0, 2.0, 3.0, 4.0, 5.0], 'mean_dose': 3.0, 'max_dose': 4.0,
            'min_dose': 2.0}
        self.assertDictEqual(expected, dvh.to_dict())

    def test_to_dict_no_diff(self):
        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]
        dvh = DVH(doses, volumes)
        expected = {'cum_volumes': [1.0, 1.0, 1.0, 0.5, 0.5, 0.0], 'doses':
            [0.0, 1.0, 2.0, 3.0, 4.0, 5.0], 'mean_dose': 3.0, 'max_dose': 
            4.0, 'min_dose': 2.0}
        self.assertDictEqual(expected, dvh.to_dict(False))
    <mask token>
    <mask token>


<mask token>

<mask token>


class TestDvh(unittest.TestCase):
    <mask token>

    def test_realistic_mean_dose(self):
        """test mean dose within 1cGy"""
        for struct, data in self.test_structs.items():
            dvh = DVH(data['doses'], data['volumes'])
            diff = dvh.mean_dose - data['monaco_dvh_mean_dose']
            self.assertLessEqual(abs(diff), 1)

    def test_realistic_min_dose(self):
        """test min dose within 1cGy"""
        for struct, data in self.test_structs.items():
            dvh = DVH(data['doses'], data['volumes'])
            diff = dvh.min_dose - data['monaco_dvh_min_dose']
            self.assertLessEqual(abs(diff), 5.0)

    def test_realistic_max_dose(self):
        """test max dose within 5cGy"""
        for struct, data in self.test_structs.items():
            dvh = DVH(data['doses'], data['volumes'])
            diff = dvh.max_dose - data['monaco_dvh_max_dose']
            self.assertLessEqual(abs(diff), 5.0)
    <mask token>

    def test_missing_volumes(self):
        with self.assertRaises(ValueError):
            dvh = DVH(doses=[1, 2])
    <mask token>

    def test_no_zero_dose_cum(self):
        doses = [1, 2, 3, 4]
        volumes = [30, 30, 10, 5]
        dvh = DVH(doses, volumes)
        self.assertEqual(dvh.mean_dose, (5.0 * 4.0 + 5 * 3 + 20 * 2) / (5.0 +
            5 + 20))
    <mask token>
    <mask token>

    def test_dmean(self):
        """TODO: Develop real worlds tests"""
        doses = [0, 1, 2, 3]
        volumes = [10, 0, 0, 10]
        dvh = DVH(doses, volumes)
        self.assertEqual(dvh.mean_dose, 1.5)

    def test_monotonic_increasing_strict(self):
        self.assertTrue(monotonic_increasing(range(4)))
        self.assertFalse(monotonic_increasing(self.test_diff_vols))
    <mask token>

    def test_diff_converted_to_cumulative(self):
        dvh = DVH(self.test_doses, self.test_diff_vols)
        self.assertAlmostEqual(dvh.cum_volumes[0], 1)

    def test_invalid_bin_count(self):
        with self.assertRaises(ValueError):
            dvh = DVH(self.test_doses[:-1], self.test_diff_vols)
    <mask token>
    <mask token>

    def test_dose_to_volume_fraction_0(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.dose_to_volume_fraction(0), self.max_dose)
    <mask token>
    <mask token>

    def test_dose_to_volume_fraction_invalid(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        with self.assertRaises(ValueError):
            dvh.dose_to_volume_fraction(100)

    def test_volume_fraction_receiving_zero_or_more_dose(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(0), 1)

    def test_volume_fraction_receiving_more_than_max_dose(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(dvh.
            max_dose + 1), 0)

    def test_volume_fraction_receiving_dose(self):
        doses = [0, 1, 2, 3]
        volumes = [10, 0, 0, 10]
        dvh = DVH(doses, volumes)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(dvh.
            mean_dose), 0.5)

    def test_to_dict(self):
        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]
        dvh = DVH(doses, volumes)
        expected = {'diff_volumes': [0.0, 0.0, 0.5, 0.0, 0.5, 0.0],
            'cum_volumes': [1.0, 1.0, 1.0, 0.5, 0.5, 0.0], 'doses': [0.0, 
            1.0, 2.0, 3.0, 4.0, 5.0], 'mean_dose': 3.0, 'max_dose': 4.0,
            'min_dose': 2.0}
        self.assertDictEqual(expected, dvh.to_dict())

    def test_to_dict_no_diff(self):
        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]
        dvh = DVH(doses, volumes)
        expected = {'cum_volumes': [1.0, 1.0, 1.0, 0.5, 0.5, 0.0], 'doses':
            [0.0, 1.0, 2.0, 3.0, 4.0, 5.0], 'mean_dose': 3.0, 'max_dose': 
            4.0, 'min_dose': 2.0}
        self.assertDictEqual(expected, dvh.to_dict(False))
    <mask token>
    <mask token>


<mask token>

<mask token>


class TestDvh(unittest.TestCase):

    def setUp(self):
        self.test_diff_vols = [0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4,
            2, 1, 0, 0, 0, 0, 0, 10, 20, 30, 40, 50, 60, 70, 60, 50, 40, 30,
            20, 10, 0, 0]
        self.test_cum_vols = [518, 518, 518, 518, 518, 518, 518, 518, 518, 
            517, 515, 512, 508, 503, 497, 493, 491, 490, 490, 490, 490, 490,
            490, 480, 460, 430, 390, 340, 280, 210, 150, 100, 60, 30, 10, 0,
            0.0]
        self.min_dose = 80
        self.max_dose = 340
        self.mean_dose = 285
        self.test_doses = np.arange(0, 370, 10)
        self.test_structs = {'Ant Scalene': {'doses': [0, 395, 405, 415, 
            425, 435, 445, 465, 475, 485, 495, 505, 515, 525, 535, 545, 555,
            565, 585, 595, 605, 615, 625, 635, 645, 655, 665, 675, 685, 715,
            725, 735, 755, 765, 775, 795, 805, 815, 825, 835, 845, 855, 865,
            875, 885, 895, 905, 915, 955, 965, 975, 985, 995, 1005, 1015, 
            1025, 1035, 1045, 1055, 1065, 1075, 1085, 1095, 1105, 1115, 
            1125, 1135, 1145, 1155, 1165, 1175, 1195, 1215, 1225, 1235, 
            1245, 1255, 1265, 1285, 1295, 1305, 1315, 1325, 1335, 1355, 
            1375, 1385, 1395, 1405, 1415, 1425, 1435, 1445, 1455, 1465, 
            1475, 1485, 1495, 1505, 1525, 1535, 1545, 1555, 1565, 1575, 
            1585, 1595, 1605, 1615, 1625, 1635, 1645, 1655, 1665, 1675, 
            1685, 1695, 1705, 1715, 1725, 1735, 1745, 1755, 1765, 1775, 
            1785, 1795, 1805, 1825, 1835, 1845, 1855, 1865, 1875, 1885, 
            1895, 1905, 1925, 1935, 1945, 1955, 1965, 1975, 1985, 1995, 
            2005, 2015, 2025, 2035, 2085, 2095, 2105, 2115, 2125, 2135, 
            2145, 2155, 2165, 2175, 2205, 2215, 2225, 2235, 2275, 2285, 
            2295, 2305, 2315, 2335, 2355, 2385, 2405, 2415, 2425, 2435, 
            2445, 2455, 2465, 2485, 2505, 2515, 2525, 2535, 2545, 2555, 
            2565, 2575, 2585, 2595, 2605, 2625, 2635, 2645, 2655, 2665, 
            2675, 2685, 2695, 2705, 2715, 2735, 2745, 2765, 2775, 2785, 
            2795, 2805, 2815, 2825, 2835, 2845, 2855, 2865, 2875, 2885, 
            2895, 2905, 2915, 2925, 2935, 2945, 2955, 2965, 2975, 2985, 
            2995, 3005, 3025, 3035, 3045, 3055, 3065, 3075, 3085, 3095, 
            3115, 3125, 3135, 3145, 3155, 3165, 3175, 3185, 3195, 3205, 
            3215, 3225, 3235, 3245, 3255, 3265, 3275, 3285, 3295, 3305, 
            3315, 3325, 3335, 3345, 3355, 3365, 3375, 3385, 3395, 3405, 
            3415, 3425, 3435, 3445, 3455, 3465, 3475, 3485, 3495, 3505, 
            3515, 3525, 3535, 3545, 3555, 3565, 3575, 3585, 3595, 3605, 
            3615, 3625, 3645, 3655, 3665, 3675, 3685, 3695, 3705, 3715, 
            3725, 3735, 3745, 3755, 3765, 3775, 3785, 3795, 3815, 3825, 
            3835, 3845, 3855, 3865, 3875, 3885, 3895, 3905, 3925, 3935, 
            3955, 3965, 3985, 3995, 4005, 4015, 4025, 4035, 4045, 4055, 
            4065, 4075, 4085, 4095, 4105, 4115, 4125, 4135, 4145, 4155, 
            4165, 4175, 4195, 4205, 4215, 4225, 4235, 4245, 4255, 4265, 
            4275, 4285, 4295, 4305, 4325, 4335, 4355, 4365, 4375, 4385, 
            4405, 4415, 4425, 4445, 4465, 4475, 4495, 4505, 4515, 4525, 
            4535, 4545, 4595, 4615, 4625, 4635, 4645, 4655, 4665, 4675, 
            4685, 4695, 4705, 4715, 4725, 4735, 4745, 4755, 4765, 4775, 
            4785, 4795, 4805, 4815, 4825, 4835, 4845, 4855, 4865, 4875, 
            4885, 4895, 4905, 4915, 4925, 4935, 4945, 4955, 4965, 4975, 
            4985, 4995, 5005, 5015, 5025, 5035, 5045, 5055, 5065, 5075, 
            5085, 5095, 5105, 5115, 5125, 5135, 5145, 5155, 5175, 5185, 
            5195, 5205, 5215, 5225, 5235, 5245, 5255, 5265, 5275, 5285, 
            5295, 5305, 5315, 5325, 5335, 5345, 5355, 5365, 5375, 5385, 
            5405, 5415, 5425, 5435, 5445, 5455, 5465, 5475, 5485, 5495, 
            5505, 5515, 5525, 5535, 5545, 5555, 5565, 5575, 5585, 5595, 
            5605, 5615, 5625, 5635, 5645, 5655, 5665, 5675, 5685, 5695, 
            5705, 5715, 5725, 5735, 5745, 5755, 5765, 5775, 5785, 5805, 
            5815, 5825, 6955, 6960], 'volumes': [8.155, 8.155, 8.132, 8.102,
            8.058, 8.02, 7.969, 7.855, 7.793, 7.738, 7.69, 7.641, 7.604, 
            7.572, 7.55, 7.527, 7.503, 7.485, 7.427, 7.411, 7.393, 7.38, 
            7.363, 7.341, 7.32, 7.292, 7.273, 7.255, 7.234, 7.156, 7.125, 
            7.102, 7.06, 7.041, 7.021, 6.993, 6.984, 6.971, 6.962, 6.957, 
            6.949, 6.94, 6.926, 6.919, 6.911, 6.899, 6.891, 6.882, 6.854, 
            6.843, 6.836, 6.83, 6.819, 6.807, 6.796, 6.784, 6.773, 6.761, 
            6.755, 6.746, 6.738, 6.727, 6.72, 6.714, 6.706, 6.699, 6.693, 
            6.684, 6.676, 6.67, 6.659, 6.643, 6.623, 6.614, 6.607, 6.596, 
            6.59, 6.585, 6.565, 6.561, 6.548, 6.544, 6.537, 6.527, 6.513, 
            6.501, 6.494, 6.489, 6.485, 6.479, 6.474, 6.471, 6.465, 6.462, 
            6.454, 6.448, 6.444, 6.436, 6.431, 6.419, 6.415, 6.407, 6.4, 
            6.396, 6.388, 6.381, 6.372, 6.369, 6.36, 6.357, 6.346, 6.341, 
            6.332, 6.33, 6.324, 6.321, 6.315, 6.312, 6.308, 6.303, 6.301, 
            6.296, 6.293, 6.288, 6.284, 6.279, 6.273, 6.265, 6.255, 6.248, 
            6.244, 6.238, 6.23, 6.228, 6.22, 6.215, 6.209, 6.195, 6.19, 
            6.181, 6.175, 6.168, 6.163, 6.155, 6.151, 6.144, 6.139, 6.132, 
            6.127, 6.107, 6.102, 6.099, 6.092, 6.088, 6.083, 6.08, 6.075, 
            6.065, 6.061, 6.046, 6.04, 6.031, 6.027, 6.003, 5.994, 5.99, 
            5.984, 5.979, 5.965, 5.957, 5.939, 5.931, 5.925, 5.921, 5.918, 
            5.911, 5.907, 5.901, 5.893, 5.883, 5.879, 5.872, 5.868, 5.865, 
            5.855, 5.85, 5.846, 5.838, 5.833, 5.829, 5.813, 5.809, 5.803, 
            5.798, 5.79, 5.785, 5.778, 5.77, 5.767, 5.761, 5.747, 5.746, 
            5.734, 5.73, 5.724, 5.719, 5.716, 5.708, 5.702, 5.7, 5.695, 
            5.689, 5.684, 5.68, 5.675, 5.671, 5.662, 5.656, 5.653, 5.647, 
            5.639, 5.634, 5.63, 5.622, 5.619, 5.612, 5.603, 5.595, 5.589, 
            5.58, 5.576, 5.57, 5.566, 5.561, 5.557, 5.551, 5.545, 5.54, 
            5.536, 5.528, 5.525, 5.519, 5.514, 5.508, 5.5, 5.495, 5.489, 
            5.481, 5.476, 5.467, 5.463, 5.45, 5.446, 5.438, 5.432, 5.425, 
            5.415, 5.409, 5.401, 5.396, 5.388, 5.383, 5.375, 5.37, 5.366, 
            5.364, 5.358, 5.356, 5.352, 5.347, 5.345, 5.338, 5.332, 5.327, 
            5.324, 5.313, 5.309, 5.303, 5.295, 5.291, 5.274, 5.267, 5.257, 
            5.249, 5.242, 5.234, 5.227, 5.215, 5.204, 5.197, 5.192, 5.185, 
            5.181, 5.174, 5.168, 5.163, 5.157, 5.152, 5.144, 5.135, 5.128, 
            5.118, 5.112, 5.094, 5.08, 5.065, 5.056, 5.051, 5.045, 5.042, 
            5.034, 5.029, 5.019, 5.013, 5.007, 4.997, 4.994, 4.986, 4.978, 
            4.972, 4.963, 4.956, 4.936, 4.919, 4.911, 4.896, 4.883, 4.873, 
            4.866, 4.856, 4.852, 4.846, 4.844, 4.84, 4.838, 4.833, 4.83, 
            4.826, 4.82, 4.817, 4.811, 4.809, 4.801, 4.796, 4.786, 4.78, 
            4.766, 4.745, 4.723, 4.695, 4.687, 4.669, 4.663, 4.647, 4.639, 
            4.621, 4.613, 4.606, 4.594, 4.58, 4.575, 4.559, 4.55, 4.544, 
            4.54, 4.531, 4.525, 4.48, 4.458, 4.445, 4.431, 4.412, 4.396, 
            4.381, 4.361, 4.345, 4.335, 4.317, 4.291, 4.274, 4.252, 4.227, 
            4.198, 4.173, 4.142, 4.12, 4.093, 4.054, 4.025, 3.997, 3.956, 
            3.918, 3.879, 3.835, 3.775, 3.718, 3.662, 3.6, 3.541, 3.48, 
            3.418, 3.376, 3.324, 3.274, 3.221, 3.175, 3.142, 3.1, 3.052, 
            3.01, 2.96, 2.918, 2.872, 2.835, 2.791, 2.75, 2.712, 2.673, 
            2.639, 2.603, 2.548, 2.506, 2.455, 2.335, 2.279, 2.209, 2.141, 
            2.07, 1.994, 1.927, 1.846, 1.766, 1.689, 1.632, 1.565, 1.502, 
            1.434, 1.375, 1.318, 1.254, 1.204, 1.151, 1.097, 1.056, 1.005, 
            0.915, 0.868, 0.832, 0.792, 0.748, 0.711, 0.675, 0.638, 0.599, 
            0.563, 0.518, 0.492, 0.468, 0.436, 0.39, 0.359, 0.341, 0.319, 
            0.288, 0.266, 0.235, 0.211, 0.197, 0.181, 0.156, 0.137, 0.12, 
            0.106, 0.087, 0.075, 0.057, 0.048, 0.037, 0.027, 0.019, 0.014, 
            0.012, 0.008, 0.003, 0.001, 0.001, 0, 0, 0],
            'monaco_dvh_mean_dose': 3752.2, 'monaco_dvh_max_dose': 5810.4,
            'monaco_dvh_min_dose': 391.9, 'monaco_dvh_volume': 8.155},
            'PTV50': {'doses': [0, 3555, 3585, 3595, 3605, 3615, 3625, 3635,
            3655, 3665, 3675, 3685, 3705, 3715, 3725, 3735, 3745, 3755, 
            3775, 3785, 3795, 3805, 3815, 3825, 3835, 3855, 3875, 3885, 
            3895, 3905, 3915, 3925, 3945, 3955, 3965, 3975, 3985, 3995, 
            4005, 4015, 4025, 4045, 4055, 4065, 4075, 4085, 4095, 4105, 
            4115, 4125, 4135, 4145, 4155, 4165, 4175, 4185, 4205, 4215, 
            4225, 4235, 4245, 4255, 4265, 4275, 4285, 4295, 4305, 4315, 
            4325, 4335, 4345, 4355, 4365, 4375, 4385, 4395, 4405, 4415, 
            4425, 4435, 4445, 4455, 4465, 4475, 4485, 4495, 4505, 4515, 
            4525, 4535, 4545, 4555, 4565, 4575, 4585, 4595, 4605, 4615, 
            4625, 4635, 4645, 4655, 4665, 4675, 4685, 4695, 4705, 4715, 
            4725, 4735, 4745, 4755, 4765, 4775, 4785, 4795, 4805, 4815, 
            4825, 4835, 4845, 4855, 4865, 4875, 4885, 4895, 4905, 4915, 
            4925, 4935, 4945, 4955, 4965, 4975, 4985, 4995, 5005, 5015, 
            5025, 5035, 5045, 5055, 5065, 5075, 5085, 5095, 5105, 5115, 
            5125, 5135, 5145, 5155, 5165, 5175, 5185, 5195, 5205, 5215, 
            5225, 5235, 5245, 5255, 5265, 5275, 5285, 5295, 5305, 5315, 
            5325, 5335, 5345, 5355, 5365, 5375, 5385, 5395, 5405, 5415, 
            5425, 5435, 5445, 5455, 5465, 5475, 5485, 5495, 5505, 5515, 
            5525, 5535, 5545, 5555, 5565, 5575, 5585, 5595, 5605, 5615, 
            5625, 5635, 5645, 5655, 5665, 5675, 5685, 5695, 5705, 5715, 
            5725, 5735, 5745, 5755, 5765, 5775, 5785, 5795, 5805, 5815, 
            5825, 5835, 5845, 5855, 5865, 5875, 5885, 5895, 5905, 5915, 
            5935, 5945, 5955, 5965, 5975, 5985, 5995, 6005, 6015, 6025, 
            6035, 6045, 6055, 6065, 6075, 6085, 6095, 6105, 6115, 6125, 
            6135, 6145, 6155, 6165, 6175, 6185, 6195, 6205, 6215, 6225, 
            6235, 6245, 6255, 6275, 6285, 6295, 6305, 6315, 6325, 6335, 
            6345, 6355, 6365, 6375, 6385, 6395, 6405, 6415, 6425, 6435, 
            6445, 6455, 6465, 6475, 6495, 6505, 6515, 6525, 6535, 6545, 
            6555, 6565, 6575, 6585, 6595, 6615, 6625, 6635, 6645, 6655, 
            6665, 6675, 6685, 6705, 6715, 6725, 6735, 6745, 6755, 6765, 
            6775, 6785, 6795, 6805, 6835, 6845, 6855, 6865, 6875, 6885, 
            6895, 6915, 6925, 6955, 6960], 'volumes': [503.55, 503.55, 
            503.547, 503.547, 503.546, 503.546, 503.544, 503.543, 503.539, 
            503.538, 503.536, 503.535, 503.531, 503.527, 503.524, 503.524, 
            503.519, 503.516, 503.506, 503.504, 503.501, 503.496, 503.494, 
            503.488, 503.483, 503.475, 503.463, 503.456, 503.447, 503.444, 
            503.437, 503.431, 503.415, 503.403, 503.396, 503.39, 503.382, 
            503.372, 503.361, 503.351, 503.339, 503.313, 503.297, 503.28, 
            503.268, 503.252, 503.232, 503.219, 503.202, 503.182, 503.161, 
            503.142, 503.122, 503.095, 503.078, 503.055, 502.993, 502.965, 
            502.931, 502.89, 502.853, 502.824, 502.786, 502.742, 502.705, 
            502.658, 502.606, 502.549, 502.507, 502.47, 502.426, 502.364, 
            502.296, 502.215, 502.123, 502.021, 501.926, 501.812, 501.693, 
            501.572, 501.409, 501.259, 501.071, 500.901, 500.701, 500.509, 
            500.289, 500.082, 499.841, 499.631, 499.414, 499.155, 498.892, 
            498.602, 498.303, 498.013, 497.719, 497.379, 497.034, 496.671, 
            496.275, 495.834, 495.359, 494.892, 494.405, 493.9, 493.358, 
            492.778, 492.147, 491.507, 490.822, 490.076, 489.288, 488.457, 
            487.645, 486.765, 485.826, 484.908, 483.894, 482.79, 481.635, 
            480.475, 479.222, 477.921, 476.512, 475.076, 473.488, 471.788, 
            470, 468.173, 466.216, 464.019, 461.764, 459.476, 456.935, 
            454.375, 451.576, 448.685, 445.574, 442.376, 438.931, 435.272, 
            431.381, 427.266, 422.727, 417.732, 412.308, 406.508, 399.991, 
            393.073, 385.506, 377.4, 368.671, 359.176, 349.297, 339.141, 
            328.753, 317.937, 306.855, 295.682, 284.517, 273.104, 261.631, 
            250.185, 238.529, 227.263, 215.981, 205.16, 194.649, 184.384, 
            174.428, 164.929, 155.956, 147.426, 139.562, 132.239, 125.344, 
            118.648, 112.3, 106.306, 100.578, 95.438, 90.599, 85.996, 81.76,
            77.718, 73.767, 70.076, 66.49, 62.922, 59.532, 56.333, 53.35, 
            50.513, 47.901, 45.409, 43.069, 40.826, 38.709, 36.767, 34.888,
            33.286, 31.767, 30.349, 29.07, 27.846, 26.646, 25.562, 24.474, 
            23.416, 22.406, 21.452, 20.429, 19.51, 18.606, 17.767, 16.964, 
            16.129, 15.335, 14.598, 13.852, 13.165, 12.461, 11.826, 11.222,
            10.7, 10.134, 9.664, 8.738, 8.28, 7.828, 7.411, 7.026, 6.634, 
            6.272, 5.954, 5.658, 5.351, 5.051, 4.745, 4.463, 4.212, 3.977, 
            3.756, 3.523, 3.311, 3.13, 2.963, 2.815, 2.692, 2.58, 2.467, 
            2.359, 2.269, 2.182, 2.09, 2.008, 1.925, 1.834, 1.742, 1.655, 
            1.505, 1.426, 1.36, 1.284, 1.221, 1.168, 1.101, 1.028, 0.964, 
            0.918, 0.879, 0.841, 0.795, 0.762, 0.727, 0.691, 0.665, 0.634, 
            0.614, 0.587, 0.557, 0.517, 0.496, 0.469, 0.449, 0.42, 0.406, 
            0.379, 0.363, 0.351, 0.327, 0.308, 0.272, 0.258, 0.236, 0.216, 
            0.192, 0.173, 0.159, 0.142, 0.114, 0.103, 0.097, 0.085, 0.07, 
            0.061, 0.057, 0.055, 0.048, 0.038, 0.031, 0.019, 0.017, 0.012, 
            0.01, 0.01, 0.006, 0.005, 0.005, 0.002, 0.002, 0],
            'monaco_dvh_mean_dose': 5277.2, 'monaco_dvh_max_dose': 6959.8,
            'monaco_dvh_min_dose': 3552.2, 'monaco_dvh_volume': 503.55},
            'prv cord': {'doses': [0, 5, 15, 25, 35, 45, 55, 65, 75, 85, 95,
            105, 115, 125, 135, 145, 155, 165, 175, 185, 195, 205, 215, 225,
            235, 245, 255, 265, 275, 285, 295, 305, 315, 325, 335, 345, 355,
            365, 375, 385, 395, 405, 415, 425, 435, 445, 455, 465, 475, 485,
            495, 505, 515, 525, 535, 545, 555, 565, 575, 585, 595, 605, 615,
            625, 635, 645, 655, 665, 675, 685, 695, 705, 715, 725, 735, 745,
            755, 765, 775, 785, 795, 805, 815, 825, 835, 845, 855, 865, 875,
            885, 895, 905, 915, 925, 935, 945, 955, 965, 975, 985, 995, 
            1005, 1015, 1025, 1035, 1045, 1055, 1065, 1075, 1085, 1095, 
            1105, 1115, 1125, 1135, 1145, 1155, 1165, 1175, 1185, 1195, 
            1205, 1215, 1225, 1235, 1245, 1255, 1265, 1275, 1285, 1295, 
            1305, 1315, 1325, 1335, 1345, 1355, 1365, 1375, 1385, 1395, 
            1405, 1415, 1425, 1435, 1445, 1455, 1465, 1475, 1485, 1495, 
            1505, 1515, 1525, 1535, 1545, 1555, 1565, 1575, 1585, 1595, 
            1605, 1625, 1635, 1645, 1655, 1665, 1675, 1685, 1695, 1705, 
            1715, 1725, 1735, 1745, 1755, 1765, 1775, 1785, 1795, 1805, 
            1815, 1825, 1835, 1845, 1855, 1865, 1875, 1885, 1895, 1905, 
            1915, 1925, 1935, 1945, 1955, 1965, 1975, 1985, 1995, 2005, 
            2015, 2025, 2035, 2045, 2065, 2075, 2085, 2095, 2105, 2115, 
            2125, 2135, 2145, 2155, 2165, 2175, 2185, 2195, 2205, 2215, 
            2225, 2235, 2245, 2255, 2265, 2275, 2285, 2295, 2305, 2315, 
            2325, 2335, 2345, 2355, 2365, 2375, 2385, 2395, 2405, 2425, 
            2435, 2445, 2465, 2475, 2485, 2495, 2505, 2515, 2525, 2535, 
            2545, 2555, 2565, 2575, 2585, 2595, 2605, 2615, 2625, 2635, 
            2655, 2665, 2685, 2695, 2705, 2715, 2725, 2735, 2745, 2755, 
            2765, 2775, 2785, 2795, 2805, 2835, 2845, 2855, 2865, 2885, 
            2895, 6955, 6960], 'volumes': [202.215, 202.215, 185.281, 
            178.426, 171.883, 166.421, 162.144, 157.958, 154.472, 151.367, 
            148.431, 145.753, 143.439, 141.707, 140.066, 138.441, 136.694, 
            135.114, 133.489, 131.856, 129.909, 127.67, 124.556, 121.016, 
            117.495, 113.781, 110.265, 107.293, 104.206, 101.475, 98.956, 
            96.835, 95.416, 94.425, 93.538, 92.733, 91.921, 91.097, 90.15, 
            88.896, 87.359, 85.697, 83.861, 81.868, 79.835, 77.708, 75.325,
            72.962, 70.615, 68.584, 66.794, 65.322, 63.94, 62.758, 61.605, 
            60.413, 59.285, 58.128, 57.042, 55.941, 55, 54.143, 53.374, 
            52.683, 51.949, 51.262, 50.66, 50.156, 49.664, 49.189, 48.707, 
            48.205, 47.698, 47.239, 46.783, 46.353, 45.919, 45.523, 45.088,
            44.702, 44.364, 44.045, 43.729, 43.462, 43.205, 42.962, 42.736,
            42.508, 42.301, 42.107, 41.9, 41.728, 41.535, 41.366, 41.178, 
            41.005, 40.827, 40.621, 40.423, 40.224, 40.008, 39.794, 39.567,
            39.353, 39.114, 38.882, 38.646, 38.408, 38.118, 37.882, 37.568,
            37.307, 37.045, 36.732, 36.432, 36.127, 35.824, 35.502, 35.141,
            34.793, 34.446, 34.062, 33.688, 33.277, 32.875, 32.393, 31.967,
            31.485, 31.006, 30.481, 29.97, 29.379, 28.812, 28.202, 27.566, 
            26.877, 26.193, 25.525, 24.791, 24.072, 23.345, 22.586, 21.809,
            20.975, 20.188, 19.355, 18.582, 17.762, 16.988, 16.176, 15.425,
            14.745, 14.056, 13.373, 12.746, 12.11, 11.542, 10.978, 10.418, 
            9.902, 9.441, 8.991, 8.191, 7.822, 7.482, 7.169, 6.887, 6.598, 
            6.352, 6.087, 5.867, 5.65, 5.434, 5.225, 5.032, 4.862, 4.67, 
            4.501, 4.325, 4.172, 4.016, 3.874, 3.728, 3.602, 3.455, 3.322, 
            3.198, 3.082, 2.972, 2.861, 2.747, 2.644, 2.558, 2.476, 2.383, 
            2.298, 2.199, 2.138, 2.061, 1.989, 1.928, 1.852, 1.791, 1.734, 
            1.669, 1.557, 1.498, 1.45, 1.398, 1.347, 1.29, 1.251, 1.2, 
            1.163, 1.12, 1.072, 1.036, 1.001, 0.959, 0.921, 0.889, 0.847, 
            0.815, 0.782, 0.75, 0.724, 0.691, 0.666, 0.637, 0.61, 0.582, 
            0.553, 0.525, 0.502, 0.477, 0.456, 0.426, 0.409, 0.388, 0.372, 
            0.33, 0.311, 0.29, 0.256, 0.243, 0.221, 0.206, 0.197, 0.181, 
            0.168, 0.158, 0.143, 0.132, 0.129, 0.12, 0.112, 0.1, 0.093, 
            0.082, 0.072, 0.069, 0.059, 0.05, 0.04, 0.038, 0.03, 0.026, 
            0.025, 0.022, 0.018, 0.016, 0.013, 0.013, 0.012, 0.012, 0.009, 
            0.006, 0.006, 0.003, 0.002, 0.002, 0, 0, 0],
            'monaco_dvh_mean_dose': 496.7, 'monaco_dvh_max_dose': 2889.2,
            'monaco_dvh_min_dose': 0, 'monaco_dvh_volume': 202.215}}

    def test_realistic_mean_dose(self):
        """test mean dose within 1cGy"""
        for struct, data in self.test_structs.items():
            dvh = DVH(data['doses'], data['volumes'])
            diff = dvh.mean_dose - data['monaco_dvh_mean_dose']
            self.assertLessEqual(abs(diff), 1)

    def test_realistic_min_dose(self):
        """test min dose within 1cGy"""
        for struct, data in self.test_structs.items():
            dvh = DVH(data['doses'], data['volumes'])
            diff = dvh.min_dose - data['monaco_dvh_min_dose']
            self.assertLessEqual(abs(diff), 5.0)

    def test_realistic_max_dose(self):
        """test max dose within 5cGy"""
        for struct, data in self.test_structs.items():
            dvh = DVH(data['doses'], data['volumes'])
            diff = dvh.max_dose - data['monaco_dvh_max_dose']
            self.assertLessEqual(abs(diff), 5.0)

    def test_missing_doses(self):
        with self.assertRaises(ValueError):
            dvh = DVH(volumes=[1, 2])

    def test_missing_volumes(self):
        with self.assertRaises(ValueError):
            dvh = DVH(doses=[1, 2])
    <mask token>

    def test_no_zero_dose_cum(self):
        doses = [1, 2, 3, 4]
        volumes = [30, 30, 10, 5]
        dvh = DVH(doses, volumes)
        self.assertEqual(dvh.mean_dose, (5.0 * 4.0 + 5 * 3 + 20 * 2) / (5.0 +
            5 + 20))
    <mask token>
    <mask token>

    def test_dmean(self):
        """TODO: Develop real worlds tests"""
        doses = [0, 1, 2, 3]
        volumes = [10, 0, 0, 10]
        dvh = DVH(doses, volumes)
        self.assertEqual(dvh.mean_dose, 1.5)

    def test_monotonic_increasing_strict(self):
        self.assertTrue(monotonic_increasing(range(4)))
        self.assertFalse(monotonic_increasing(self.test_diff_vols))
    <mask token>

    def test_diff_converted_to_cumulative(self):
        dvh = DVH(self.test_doses, self.test_diff_vols)
        self.assertAlmostEqual(dvh.cum_volumes[0], 1)

    def test_invalid_bin_count(self):
        with self.assertRaises(ValueError):
            dvh = DVH(self.test_doses[:-1], self.test_diff_vols)
    <mask token>
    <mask token>

    def test_dose_to_volume_fraction_0(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.dose_to_volume_fraction(0), self.max_dose)

    def test_dose_to_volume_fraction_1(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.dose_to_volume_fraction(1), self.min_dose)

    def test_dose_to_volume_fraction_mid(self):
        """ A volume fraction of 0.9999999999 should give just slightly more than min dose"""
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.dose_to_volume_fraction(0.9999999999),
            self.min_dose, places=4)
        self.assertGreater(dvh.dose_to_volume_fraction(0.9999999999), self.
            min_dose)

    def test_dose_to_volume_fraction_invalid(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        with self.assertRaises(ValueError):
            dvh.dose_to_volume_fraction(100)

    def test_volume_fraction_receiving_zero_or_more_dose(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(0), 1)

    def test_volume_fraction_receiving_more_than_max_dose(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(dvh.
            max_dose + 1), 0)

    def test_volume_fraction_receiving_dose(self):
        doses = [0, 1, 2, 3]
        volumes = [10, 0, 0, 10]
        dvh = DVH(doses, volumes)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(dvh.
            mean_dose), 0.5)

    def test_to_dict(self):
        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]
        dvh = DVH(doses, volumes)
        expected = {'diff_volumes': [0.0, 0.0, 0.5, 0.0, 0.5, 0.0],
            'cum_volumes': [1.0, 1.0, 1.0, 0.5, 0.5, 0.0], 'doses': [0.0, 
            1.0, 2.0, 3.0, 4.0, 5.0], 'mean_dose': 3.0, 'max_dose': 4.0,
            'min_dose': 2.0}
        self.assertDictEqual(expected, dvh.to_dict())

    def test_to_dict_no_diff(self):
        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]
        dvh = DVH(doses, volumes)
        expected = {'cum_volumes': [1.0, 1.0, 1.0, 0.5, 0.5, 0.0], 'doses':
            [0.0, 1.0, 2.0, 3.0, 4.0, 5.0], 'mean_dose': 3.0, 'max_dose': 
            4.0, 'min_dose': 2.0}
        self.assertDictEqual(expected, dvh.to_dict(False))
    <mask token>
    <mask token>


<mask token>

<mask token>


class TestDvh(unittest.TestCase):

    def setUp(self):
        self.test_diff_vols = [0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4,
            2, 1, 0, 0, 0, 0, 0, 10, 20, 30, 40, 50, 60, 70, 60, 50, 40, 30,
            20, 10, 0, 0]
        self.test_cum_vols = [518, 518, 518, 518, 518, 518, 518, 518, 518, 
            517, 515, 512, 508, 503, 497, 493, 491, 490, 490, 490, 490, 490,
            490, 480, 460, 430, 390, 340, 280, 210, 150, 100, 60, 30, 10, 0,
            0.0]
        self.min_dose = 80
        self.max_dose = 340
        self.mean_dose = 285
        self.test_doses = np.arange(0, 370, 10)
        self.test_structs = {'Ant Scalene': {'doses': [0, 395, 405, 415, 
            425, 435, 445, 465, 475, 485, 495, 505, 515, 525, 535, 545, 555,
            565, 585, 595, 605, 615, 625, 635, 645, 655, 665, 675, 685, 715,
            725, 735, 755, 765, 775, 795, 805, 815, 825, 835, 845, 855, 865,
            875, 885, 895, 905, 915, 955, 965, 975, 985, 995, 1005, 1015, 
            1025, 1035, 1045, 1055, 1065, 1075, 1085, 1095, 1105, 1115, 
            1125, 1135, 1145, 1155, 1165, 1175, 1195, 1215, 1225, 1235, 
            1245, 1255, 1265, 1285, 1295, 1305, 1315, 1325, 1335, 1355, 
            1375, 1385, 1395, 1405, 1415, 1425, 1435, 1445, 1455, 1465, 
            1475, 1485, 1495, 1505, 1525, 1535, 1545, 1555, 1565, 1575, 
            1585, 1595, 1605, 1615, 1625, 1635, 1645, 1655, 1665, 1675, 
            1685, 1695, 1705, 1715, 1725, 1735, 1745, 1755, 1765, 1775, 
            1785, 1795, 1805, 1825, 1835, 1845, 1855, 1865, 1875, 1885, 
            1895, 1905, 1925, 1935, 1945, 1955, 1965, 1975, 1985, 1995, 
            2005, 2015, 2025, 2035, 2085, 2095, 2105, 2115, 2125, 2135, 
            2145, 2155, 2165, 2175, 2205, 2215, 2225, 2235, 2275, 2285, 
            2295, 2305, 2315, 2335, 2355, 2385, 2405, 2415, 2425, 2435, 
            2445, 2455, 2465, 2485, 2505, 2515, 2525, 2535, 2545, 2555, 
            2565, 2575, 2585, 2595, 2605, 2625, 2635, 2645, 2655, 2665, 
            2675, 2685, 2695, 2705, 2715, 2735, 2745, 2765, 2775, 2785, 
            2795, 2805, 2815, 2825, 2835, 2845, 2855, 2865, 2875, 2885, 
            2895, 2905, 2915, 2925, 2935, 2945, 2955, 2965, 2975, 2985, 
            2995, 3005, 3025, 3035, 3045, 3055, 3065, 3075, 3085, 3095, 
            3115, 3125, 3135, 3145, 3155, 3165, 3175, 3185, 3195, 3205, 
            3215, 3225, 3235, 3245, 3255, 3265, 3275, 3285, 3295, 3305, 
            3315, 3325, 3335, 3345, 3355, 3365, 3375, 3385, 3395, 3405, 
            3415, 3425, 3435, 3445, 3455, 3465, 3475, 3485, 3495, 3505, 
            3515, 3525, 3535, 3545, 3555, 3565, 3575, 3585, 3595, 3605, 
            3615, 3625, 3645, 3655, 3665, 3675, 3685, 3695, 3705, 3715, 
            3725, 3735, 3745, 3755, 3765, 3775, 3785, 3795, 3815, 3825, 
            3835, 3845, 3855, 3865, 3875, 3885, 3895, 3905, 3925, 3935, 
            3955, 3965, 3985, 3995, 4005, 4015, 4025, 4035, 4045, 4055, 
            4065, 4075, 4085, 4095, 4105, 4115, 4125, 4135, 4145, 4155, 
            4165, 4175, 4195, 4205, 4215, 4225, 4235, 4245, 4255, 4265, 
            4275, 4285, 4295, 4305, 4325, 4335, 4355, 4365, 4375, 4385, 
            4405, 4415, 4425, 4445, 4465, 4475, 4495, 4505, 4515, 4525, 
            4535, 4545, 4595, 4615, 4625, 4635, 4645, 4655, 4665, 4675, 
            4685, 4695, 4705, 4715, 4725, 4735, 4745, 4755, 4765, 4775, 
            4785, 4795, 4805, 4815, 4825, 4835, 4845, 4855, 4865, 4875, 
            4885, 4895, 4905, 4915, 4925, 4935, 4945, 4955, 4965, 4975, 
            4985, 4995, 5005, 5015, 5025, 5035, 5045, 5055, 5065, 5075, 
            5085, 5095, 5105, 5115, 5125, 5135, 5145, 5155, 5175, 5185, 
            5195, 5205, 5215, 5225, 5235, 5245, 5255, 5265, 5275, 5285, 
            5295, 5305, 5315, 5325, 5335, 5345, 5355, 5365, 5375, 5385, 
            5405, 5415, 5425, 5435, 5445, 5455, 5465, 5475, 5485, 5495, 
            5505, 5515, 5525, 5535, 5545, 5555, 5565, 5575, 5585, 5595, 
            5605, 5615, 5625, 5635, 5645, 5655, 5665, 5675, 5685, 5695, 
            5705, 5715, 5725, 5735, 5745, 5755, 5765, 5775, 5785, 5805, 
            5815, 5825, 6955, 6960], 'volumes': [8.155, 8.155, 8.132, 8.102,
            8.058, 8.02, 7.969, 7.855, 7.793, 7.738, 7.69, 7.641, 7.604, 
            7.572, 7.55, 7.527, 7.503, 7.485, 7.427, 7.411, 7.393, 7.38, 
            7.363, 7.341, 7.32, 7.292, 7.273, 7.255, 7.234, 7.156, 7.125, 
            7.102, 7.06, 7.041, 7.021, 6.993, 6.984, 6.971, 6.962, 6.957, 
            6.949, 6.94, 6.926, 6.919, 6.911, 6.899, 6.891, 6.882, 6.854, 
            6.843, 6.836, 6.83, 6.819, 6.807, 6.796, 6.784, 6.773, 6.761, 
            6.755, 6.746, 6.738, 6.727, 6.72, 6.714, 6.706, 6.699, 6.693, 
            6.684, 6.676, 6.67, 6.659, 6.643, 6.623, 6.614, 6.607, 6.596, 
            6.59, 6.585, 6.565, 6.561, 6.548, 6.544, 6.537, 6.527, 6.513, 
            6.501, 6.494, 6.489, 6.485, 6.479, 6.474, 6.471, 6.465, 6.462, 
            6.454, 6.448, 6.444, 6.436, 6.431, 6.419, 6.415, 6.407, 6.4, 
            6.396, 6.388, 6.381, 6.372, 6.369, 6.36, 6.357, 6.346, 6.341, 
            6.332, 6.33, 6.324, 6.321, 6.315, 6.312, 6.308, 6.303, 6.301, 
            6.296, 6.293, 6.288, 6.284, 6.279, 6.273, 6.265, 6.255, 6.248, 
            6.244, 6.238, 6.23, 6.228, 6.22, 6.215, 6.209, 6.195, 6.19, 
            6.181, 6.175, 6.168, 6.163, 6.155, 6.151, 6.144, 6.139, 6.132, 
            6.127, 6.107, 6.102, 6.099, 6.092, 6.088, 6.083, 6.08, 6.075, 
            6.065, 6.061, 6.046, 6.04, 6.031, 6.027, 6.003, 5.994, 5.99, 
            5.984, 5.979, 5.965, 5.957, 5.939, 5.931, 5.925, 5.921, 5.918, 
            5.911, 5.907, 5.901, 5.893, 5.883, 5.879, 5.872, 5.868, 5.865, 
            5.855, 5.85, 5.846, 5.838, 5.833, 5.829, 5.813, 5.809, 5.803, 
            5.798, 5.79, 5.785, 5.778, 5.77, 5.767, 5.761, 5.747, 5.746, 
            5.734, 5.73, 5.724, 5.719, 5.716, 5.708, 5.702, 5.7, 5.695, 
            5.689, 5.684, 5.68, 5.675, 5.671, 5.662, 5.656, 5.653, 5.647, 
            5.639, 5.634, 5.63, 5.622, 5.619, 5.612, 5.603, 5.595, 5.589, 
            5.58, 5.576, 5.57, 5.566, 5.561, 5.557, 5.551, 5.545, 5.54, 
            5.536, 5.528, 5.525, 5.519, 5.514, 5.508, 5.5, 5.495, 5.489, 
            5.481, 5.476, 5.467, 5.463, 5.45, 5.446, 5.438, 5.432, 5.425, 
            5.415, 5.409, 5.401, 5.396, 5.388, 5.383, 5.375, 5.37, 5.366, 
            5.364, 5.358, 5.356, 5.352, 5.347, 5.345, 5.338, 5.332, 5.327, 
            5.324, 5.313, 5.309, 5.303, 5.295, 5.291, 5.274, 5.267, 5.257, 
            5.249, 5.242, 5.234, 5.227, 5.215, 5.204, 5.197, 5.192, 5.185, 
            5.181, 5.174, 5.168, 5.163, 5.157, 5.152, 5.144, 5.135, 5.128, 
            5.118, 5.112, 5.094, 5.08, 5.065, 5.056, 5.051, 5.045, 5.042, 
            5.034, 5.029, 5.019, 5.013, 5.007, 4.997, 4.994, 4.986, 4.978, 
            4.972, 4.963, 4.956, 4.936, 4.919, 4.911, 4.896, 4.883, 4.873, 
            4.866, 4.856, 4.852, 4.846, 4.844, 4.84, 4.838, 4.833, 4.83, 
            4.826, 4.82, 4.817, 4.811, 4.809, 4.801, 4.796, 4.786, 4.78, 
            4.766, 4.745, 4.723, 4.695, 4.687, 4.669, 4.663, 4.647, 4.639, 
            4.621, 4.613, 4.606, 4.594, 4.58, 4.575, 4.559, 4.55, 4.544, 
            4.54, 4.531, 4.525, 4.48, 4.458, 4.445, 4.431, 4.412, 4.396, 
            4.381, 4.361, 4.345, 4.335, 4.317, 4.291, 4.274, 4.252, 4.227, 
            4.198, 4.173, 4.142, 4.12, 4.093, 4.054, 4.025, 3.997, 3.956, 
            3.918, 3.879, 3.835, 3.775, 3.718, 3.662, 3.6, 3.541, 3.48, 
            3.418, 3.376, 3.324, 3.274, 3.221, 3.175, 3.142, 3.1, 3.052, 
            3.01, 2.96, 2.918, 2.872, 2.835, 2.791, 2.75, 2.712, 2.673, 
            2.639, 2.603, 2.548, 2.506, 2.455, 2.335, 2.279, 2.209, 2.141, 
            2.07, 1.994, 1.927, 1.846, 1.766, 1.689, 1.632, 1.565, 1.502, 
            1.434, 1.375, 1.318, 1.254, 1.204, 1.151, 1.097, 1.056, 1.005, 
            0.915, 0.868, 0.832, 0.792, 0.748, 0.711, 0.675, 0.638, 0.599, 
            0.563, 0.518, 0.492, 0.468, 0.436, 0.39, 0.359, 0.341, 0.319, 
            0.288, 0.266, 0.235, 0.211, 0.197, 0.181, 0.156, 0.137, 0.12, 
            0.106, 0.087, 0.075, 0.057, 0.048, 0.037, 0.027, 0.019, 0.014, 
            0.012, 0.008, 0.003, 0.001, 0.001, 0, 0, 0],
            'monaco_dvh_mean_dose': 3752.2, 'monaco_dvh_max_dose': 5810.4,
            'monaco_dvh_min_dose': 391.9, 'monaco_dvh_volume': 8.155},
            'PTV50': {'doses': [0, 3555, 3585, 3595, 3605, 3615, 3625, 3635,
            3655, 3665, 3675, 3685, 3705, 3715, 3725, 3735, 3745, 3755, 
            3775, 3785, 3795, 3805, 3815, 3825, 3835, 3855, 3875, 3885, 
            3895, 3905, 3915, 3925, 3945, 3955, 3965, 3975, 3985, 3995, 
            4005, 4015, 4025, 4045, 4055, 4065, 4075, 4085, 4095, 4105, 
            4115, 4125, 4135, 4145, 4155, 4165, 4175, 4185, 4205, 4215, 
            4225, 4235, 4245, 4255, 4265, 4275, 4285, 4295, 4305, 4315, 
            4325, 4335, 4345, 4355, 4365, 4375, 4385, 4395, 4405, 4415, 
            4425, 4435, 4445, 4455, 4465, 4475, 4485, 4495, 4505, 4515, 
            4525, 4535, 4545, 4555, 4565, 4575, 4585, 4595, 4605, 4615, 
            4625, 4635, 4645, 4655, 4665, 4675, 4685, 4695, 4705, 4715, 
            4725, 4735, 4745, 4755, 4765, 4775, 4785, 4795, 4805, 4815, 
            4825, 4835, 4845, 4855, 4865, 4875, 4885, 4895, 4905, 4915, 
            4925, 4935, 4945, 4955, 4965, 4975, 4985, 4995, 5005, 5015, 
            5025, 5035, 5045, 5055, 5065, 5075, 5085, 5095, 5105, 5115, 
            5125, 5135, 5145, 5155, 5165, 5175, 5185, 5195, 5205, 5215, 
            5225, 5235, 5245, 5255, 5265, 5275, 5285, 5295, 5305, 5315, 
            5325, 5335, 5345, 5355, 5365, 5375, 5385, 5395, 5405, 5415, 
            5425, 5435, 5445, 5455, 5465, 5475, 5485, 5495, 5505, 5515, 
            5525, 5535, 5545, 5555, 5565, 5575, 5585, 5595, 5605, 5615, 
            5625, 5635, 5645, 5655, 5665, 5675, 5685, 5695, 5705, 5715, 
            5725, 5735, 5745, 5755, 5765, 5775, 5785, 5795, 5805, 5815, 
            5825, 5835, 5845, 5855, 5865, 5875, 5885, 5895, 5905, 5915, 
            5935, 5945, 5955, 5965, 5975, 5985, 5995, 6005, 6015, 6025, 
            6035, 6045, 6055, 6065, 6075, 6085, 6095, 6105, 6115, 6125, 
            6135, 6145, 6155, 6165, 6175, 6185, 6195, 6205, 6215, 6225, 
            6235, 6245, 6255, 6275, 6285, 6295, 6305, 6315, 6325, 6335, 
            6345, 6355, 6365, 6375, 6385, 6395, 6405, 6415, 6425, 6435, 
            6445, 6455, 6465, 6475, 6495, 6505, 6515, 6525, 6535, 6545, 
            6555, 6565, 6575, 6585, 6595, 6615, 6625, 6635, 6645, 6655, 
            6665, 6675, 6685, 6705, 6715, 6725, 6735, 6745, 6755, 6765, 
            6775, 6785, 6795, 6805, 6835, 6845, 6855, 6865, 6875, 6885, 
            6895, 6915, 6925, 6955, 6960], 'volumes': [503.55, 503.55, 
            503.547, 503.547, 503.546, 503.546, 503.544, 503.543, 503.539, 
            503.538, 503.536, 503.535, 503.531, 503.527, 503.524, 503.524, 
            503.519, 503.516, 503.506, 503.504, 503.501, 503.496, 503.494, 
            503.488, 503.483, 503.475, 503.463, 503.456, 503.447, 503.444, 
            503.437, 503.431, 503.415, 503.403, 503.396, 503.39, 503.382, 
            503.372, 503.361, 503.351, 503.339, 503.313, 503.297, 503.28, 
            503.268, 503.252, 503.232, 503.219, 503.202, 503.182, 503.161, 
            503.142, 503.122, 503.095, 503.078, 503.055, 502.993, 502.965, 
            502.931, 502.89, 502.853, 502.824, 502.786, 502.742, 502.705, 
            502.658, 502.606, 502.549, 502.507, 502.47, 502.426, 502.364, 
            502.296, 502.215, 502.123, 502.021, 501.926, 501.812, 501.693, 
            501.572, 501.409, 501.259, 501.071, 500.901, 500.701, 500.509, 
            500.289, 500.082, 499.841, 499.631, 499.414, 499.155, 498.892, 
            498.602, 498.303, 498.013, 497.719, 497.379, 497.034, 496.671, 
            496.275, 495.834, 495.359, 494.892, 494.405, 493.9, 493.358, 
            492.778, 492.147, 491.507, 490.822, 490.076, 489.288, 488.457, 
            487.645, 486.765, 485.826, 484.908, 483.894, 482.79, 481.635, 
            480.475, 479.222, 477.921, 476.512, 475.076, 473.488, 471.788, 
            470, 468.173, 466.216, 464.019, 461.764, 459.476, 456.935, 
            454.375, 451.576, 448.685, 445.574, 442.376, 438.931, 435.272, 
            431.381, 427.266, 422.727, 417.732, 412.308, 406.508, 399.991, 
            393.073, 385.506, 377.4, 368.671, 359.176, 349.297, 339.141, 
            328.753, 317.937, 306.855, 295.682, 284.517, 273.104, 261.631, 
            250.185, 238.529, 227.263, 215.981, 205.16, 194.649, 184.384, 
            174.428, 164.929, 155.956, 147.426, 139.562, 132.239, 125.344, 
            118.648, 112.3, 106.306, 100.578, 95.438, 90.599, 85.996, 81.76,
            77.718, 73.767, 70.076, 66.49, 62.922, 59.532, 56.333, 53.35, 
            50.513, 47.901, 45.409, 43.069, 40.826, 38.709, 36.767, 34.888,
            33.286, 31.767, 30.349, 29.07, 27.846, 26.646, 25.562, 24.474, 
            23.416, 22.406, 21.452, 20.429, 19.51, 18.606, 17.767, 16.964, 
            16.129, 15.335, 14.598, 13.852, 13.165, 12.461, 11.826, 11.222,
            10.7, 10.134, 9.664, 8.738, 8.28, 7.828, 7.411, 7.026, 6.634, 
            6.272, 5.954, 5.658, 5.351, 5.051, 4.745, 4.463, 4.212, 3.977, 
            3.756, 3.523, 3.311, 3.13, 2.963, 2.815, 2.692, 2.58, 2.467, 
            2.359, 2.269, 2.182, 2.09, 2.008, 1.925, 1.834, 1.742, 1.655, 
            1.505, 1.426, 1.36, 1.284, 1.221, 1.168, 1.101, 1.028, 0.964, 
            0.918, 0.879, 0.841, 0.795, 0.762, 0.727, 0.691, 0.665, 0.634, 
            0.614, 0.587, 0.557, 0.517, 0.496, 0.469, 0.449, 0.42, 0.406, 
            0.379, 0.363, 0.351, 0.327, 0.308, 0.272, 0.258, 0.236, 0.216, 
            0.192, 0.173, 0.159, 0.142, 0.114, 0.103, 0.097, 0.085, 0.07, 
            0.061, 0.057, 0.055, 0.048, 0.038, 0.031, 0.019, 0.017, 0.012, 
            0.01, 0.01, 0.006, 0.005, 0.005, 0.002, 0.002, 0],
            'monaco_dvh_mean_dose': 5277.2, 'monaco_dvh_max_dose': 6959.8,
            'monaco_dvh_min_dose': 3552.2, 'monaco_dvh_volume': 503.55},
            'prv cord': {'doses': [0, 5, 15, 25, 35, 45, 55, 65, 75, 85, 95,
            105, 115, 125, 135, 145, 155, 165, 175, 185, 195, 205, 215, 225,
            235, 245, 255, 265, 275, 285, 295, 305, 315, 325, 335, 345, 355,
            365, 375, 385, 395, 405, 415, 425, 435, 445, 455, 465, 475, 485,
            495, 505, 515, 525, 535, 545, 555, 565, 575, 585, 595, 605, 615,
            625, 635, 645, 655, 665, 675, 685, 695, 705, 715, 725, 735, 745,
            755, 765, 775, 785, 795, 805, 815, 825, 835, 845, 855, 865, 875,
            885, 895, 905, 915, 925, 935, 945, 955, 965, 975, 985, 995, 
            1005, 1015, 1025, 1035, 1045, 1055, 1065, 1075, 1085, 1095, 
            1105, 1115, 1125, 1135, 1145, 1155, 1165, 1175, 1185, 1195, 
            1205, 1215, 1225, 1235, 1245, 1255, 1265, 1275, 1285, 1295, 
            1305, 1315, 1325, 1335, 1345, 1355, 1365, 1375, 1385, 1395, 
            1405, 1415, 1425, 1435, 1445, 1455, 1465, 1475, 1485, 1495, 
            1505, 1515, 1525, 1535, 1545, 1555, 1565, 1575, 1585, 1595, 
            1605, 1625, 1635, 1645, 1655, 1665, 1675, 1685, 1695, 1705, 
            1715, 1725, 1735, 1745, 1755, 1765, 1775, 1785, 1795, 1805, 
            1815, 1825, 1835, 1845, 1855, 1865, 1875, 1885, 1895, 1905, 
            1915, 1925, 1935, 1945, 1955, 1965, 1975, 1985, 1995, 2005, 
            2015, 2025, 2035, 2045, 2065, 2075, 2085, 2095, 2105, 2115, 
            2125, 2135, 2145, 2155, 2165, 2175, 2185, 2195, 2205, 2215, 
            2225, 2235, 2245, 2255, 2265, 2275, 2285, 2295, 2305, 2315, 
            2325, 2335, 2345, 2355, 2365, 2375, 2385, 2395, 2405, 2425, 
            2435, 2445, 2465, 2475, 2485, 2495, 2505, 2515, 2525, 2535, 
            2545, 2555, 2565, 2575, 2585, 2595, 2605, 2615, 2625, 2635, 
            2655, 2665, 2685, 2695, 2705, 2715, 2725, 2735, 2745, 2755, 
            2765, 2775, 2785, 2795, 2805, 2835, 2845, 2855, 2865, 2885, 
            2895, 6955, 6960], 'volumes': [202.215, 202.215, 185.281, 
            178.426, 171.883, 166.421, 162.144, 157.958, 154.472, 151.367, 
            148.431, 145.753, 143.439, 141.707, 140.066, 138.441, 136.694, 
            135.114, 133.489, 131.856, 129.909, 127.67, 124.556, 121.016, 
            117.495, 113.781, 110.265, 107.293, 104.206, 101.475, 98.956, 
            96.835, 95.416, 94.425, 93.538, 92.733, 91.921, 91.097, 90.15, 
            88.896, 87.359, 85.697, 83.861, 81.868, 79.835, 77.708, 75.325,
            72.962, 70.615, 68.584, 66.794, 65.322, 63.94, 62.758, 61.605, 
            60.413, 59.285, 58.128, 57.042, 55.941, 55, 54.143, 53.374, 
            52.683, 51.949, 51.262, 50.66, 50.156, 49.664, 49.189, 48.707, 
            48.205, 47.698, 47.239, 46.783, 46.353, 45.919, 45.523, 45.088,
            44.702, 44.364, 44.045, 43.729, 43.462, 43.205, 42.962, 42.736,
            42.508, 42.301, 42.107, 41.9, 41.728, 41.535, 41.366, 41.178, 
            41.005, 40.827, 40.621, 40.423, 40.224, 40.008, 39.794, 39.567,
            39.353, 39.114, 38.882, 38.646, 38.408, 38.118, 37.882, 37.568,
            37.307, 37.045, 36.732, 36.432, 36.127, 35.824, 35.502, 35.141,
            34.793, 34.446, 34.062, 33.688, 33.277, 32.875, 32.393, 31.967,
            31.485, 31.006, 30.481, 29.97, 29.379, 28.812, 28.202, 27.566, 
            26.877, 26.193, 25.525, 24.791, 24.072, 23.345, 22.586, 21.809,
            20.975, 20.188, 19.355, 18.582, 17.762, 16.988, 16.176, 15.425,
            14.745, 14.056, 13.373, 12.746, 12.11, 11.542, 10.978, 10.418, 
            9.902, 9.441, 8.991, 8.191, 7.822, 7.482, 7.169, 6.887, 6.598, 
            6.352, 6.087, 5.867, 5.65, 5.434, 5.225, 5.032, 4.862, 4.67, 
            4.501, 4.325, 4.172, 4.016, 3.874, 3.728, 3.602, 3.455, 3.322, 
            3.198, 3.082, 2.972, 2.861, 2.747, 2.644, 2.558, 2.476, 2.383, 
            2.298, 2.199, 2.138, 2.061, 1.989, 1.928, 1.852, 1.791, 1.734, 
            1.669, 1.557, 1.498, 1.45, 1.398, 1.347, 1.29, 1.251, 1.2, 
            1.163, 1.12, 1.072, 1.036, 1.001, 0.959, 0.921, 0.889, 0.847, 
            0.815, 0.782, 0.75, 0.724, 0.691, 0.666, 0.637, 0.61, 0.582, 
            0.553, 0.525, 0.502, 0.477, 0.456, 0.426, 0.409, 0.388, 0.372, 
            0.33, 0.311, 0.29, 0.256, 0.243, 0.221, 0.206, 0.197, 0.181, 
            0.168, 0.158, 0.143, 0.132, 0.129, 0.12, 0.112, 0.1, 0.093, 
            0.082, 0.072, 0.069, 0.059, 0.05, 0.04, 0.038, 0.03, 0.026, 
            0.025, 0.022, 0.018, 0.016, 0.013, 0.013, 0.012, 0.012, 0.009, 
            0.006, 0.006, 0.003, 0.002, 0.002, 0, 0, 0],
            'monaco_dvh_mean_dose': 496.7, 'monaco_dvh_max_dose': 2889.2,
            'monaco_dvh_min_dose': 0, 'monaco_dvh_volume': 202.215}}

    def test_realistic_mean_dose(self):
        """test mean dose within 1cGy"""
        for struct, data in self.test_structs.items():
            dvh = DVH(data['doses'], data['volumes'])
            diff = dvh.mean_dose - data['monaco_dvh_mean_dose']
            self.assertLessEqual(abs(diff), 1)

    def test_realistic_min_dose(self):
        """test min dose within 1cGy"""
        for struct, data in self.test_structs.items():
            dvh = DVH(data['doses'], data['volumes'])
            diff = dvh.min_dose - data['monaco_dvh_min_dose']
            self.assertLessEqual(abs(diff), 5.0)

    def test_realistic_max_dose(self):
        """test max dose within 5cGy"""
        for struct, data in self.test_structs.items():
            dvh = DVH(data['doses'], data['volumes'])
            diff = dvh.max_dose - data['monaco_dvh_max_dose']
            self.assertLessEqual(abs(diff), 5.0)

    def test_missing_doses(self):
        with self.assertRaises(ValueError):
            dvh = DVH(volumes=[1, 2])

    def test_missing_volumes(self):
        with self.assertRaises(ValueError):
            dvh = DVH(doses=[1, 2])

    def test_no_zero_dose_dif(self):
        doses = [1, 2, 3]
        volumes = [30, 0, 10]
        dvh = DVH(doses, volumes)
        self.assertEqual(dvh.mean_dose, 1.5)

    def test_no_zero_dose_cum(self):
        doses = [1, 2, 3, 4]
        volumes = [30, 30, 10, 5]
        dvh = DVH(doses, volumes)
        self.assertEqual(dvh.mean_dose, (5.0 * 4.0 + 5 * 3 + 20 * 2) / (5.0 +
            5 + 20))

    def test_dmax(self):
        dvh = DVH(self.test_doses, self.test_diff_vols)
        self.assertEqual(dvh.max_dose, self.max_dose)

    def test_dmin(self):
        dvh = DVH(self.test_doses, self.test_diff_vols)
        self.assertEqual(dvh.min_dose, self.min_dose)

    def test_dmean(self):
        """TODO: Develop real worlds tests"""
        doses = [0, 1, 2, 3]
        volumes = [10, 0, 0, 10]
        dvh = DVH(doses, volumes)
        self.assertEqual(dvh.mean_dose, 1.5)

    def test_monotonic_increasing_strict(self):
        self.assertTrue(monotonic_increasing(range(4)))
        self.assertFalse(monotonic_increasing(self.test_diff_vols))

    def test_monotonic_decreasing(self):
        self.assertFalse(monotonic_decreasing(self.test_diff_vols))
        self.assertTrue(monotonic_decreasing(list(reversed(range(4)))))

    def test_diff_converted_to_cumulative(self):
        dvh = DVH(self.test_doses, self.test_diff_vols)
        self.assertAlmostEqual(dvh.cum_volumes[0], 1)

    def test_invalid_bin_count(self):
        with self.assertRaises(ValueError):
            dvh = DVH(self.test_doses[:-1], self.test_diff_vols)
    <mask token>
    <mask token>

    def test_dose_to_volume_fraction_0(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.dose_to_volume_fraction(0), self.max_dose)

    def test_dose_to_volume_fraction_1(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.dose_to_volume_fraction(1), self.min_dose)

    def test_dose_to_volume_fraction_mid(self):
        """ A volume fraction of 0.9999999999 should give just slightly more than min dose"""
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.dose_to_volume_fraction(0.9999999999),
            self.min_dose, places=4)
        self.assertGreater(dvh.dose_to_volume_fraction(0.9999999999), self.
            min_dose)

    def test_dose_to_volume_fraction_invalid(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        with self.assertRaises(ValueError):
            dvh.dose_to_volume_fraction(100)

    def test_volume_fraction_receiving_zero_or_more_dose(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(0), 1)

    def test_volume_fraction_receiving_more_than_max_dose(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(dvh.
            max_dose + 1), 0)

    def test_volume_fraction_receiving_dose(self):
        doses = [0, 1, 2, 3]
        volumes = [10, 0, 0, 10]
        dvh = DVH(doses, volumes)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(dvh.
            mean_dose), 0.5)

    def test_to_dict(self):
        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]
        dvh = DVH(doses, volumes)
        expected = {'diff_volumes': [0.0, 0.0, 0.5, 0.0, 0.5, 0.0],
            'cum_volumes': [1.0, 1.0, 1.0, 0.5, 0.5, 0.0], 'doses': [0.0, 
            1.0, 2.0, 3.0, 4.0, 5.0], 'mean_dose': 3.0, 'max_dose': 4.0,
            'min_dose': 2.0}
        self.assertDictEqual(expected, dvh.to_dict())

    def test_to_dict_no_diff(self):
        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]
        dvh = DVH(doses, volumes)
        expected = {'cum_volumes': [1.0, 1.0, 1.0, 0.5, 0.5, 0.0], 'doses':
            [0.0, 1.0, 2.0, 3.0, 4.0, 5.0], 'mean_dose': 3.0, 'max_dose': 
            4.0, 'min_dose': 2.0}
        self.assertDictEqual(expected, dvh.to_dict(False))

    def test_json_serialze(self):
        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]
        dvh = DVH(doses, volumes)
        expected = {'diff_volumes': [0.0, 0.0, 0.5, 0.0, 0.5, 0.0],
            'cum_volumes': [1.0, 1.0, 1.0, 0.5, 0.5, 0.0], 'doses': [0.0, 
            1.0, 2.0, 3.0, 4.0, 5.0], 'mean_dose': 3.0, 'max_dose': 4.0,
            'min_dose': 2.0}
        self.assertDictEqual(json.loads(json.dumps(expected)), json.loads(
            dvh.serialize()))

    def test_json_serialze_invalid(self):
        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]
        dvh = DVH(doses, volumes)
        with self.assertRaises(TypeError):
            dvh.serialize(method='blah')


<mask token>

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
test_dvh
----------------------------------

Tests for `dvh` module.
"""

import json
import unittest2 as unittest
import numpy as np
from dvh import DVH, monotonic_increasing, monotonic_decreasing


class TestDvh(unittest.TestCase):

    def setUp(self):

        self.test_diff_vols = [0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 2, 1, 0, 0, 0, 0, 0, 10, 20, 30, 40, 50, 60, 70, 60, 50, 40, 30, 20, 10, 0, 0]
        self.test_cum_vols = [ 518,  518,  518,  518,  518,  518,  518,  518,  518,  517,  515,  512,  508,  503,  497,  493,  491,  490,  490,  490,  490,  490,  490,  480,  460,  430,  390,  340,  280,  210,  150,  100,   60,   30,   10,    0,  0.]
        self.min_dose = 80
        self.max_dose = 340
        self.mean_dose = 285
        self.test_doses = np.arange(0, 370, 10)



        self.test_structs = {
            "Ant Scalene" : {
                "doses": [0, 395, 405, 415, 425, 435, 445, 465, 475, 485, 495, 505, 515, 525, 535, 545, 555, 565, 585, 595, 605, 615, 625, 635, 645, 655, 665, 675, 685, 715, 725, 735, 755, 765, 775, 795, 805, 815, 825, 835, 845, 855, 865, 875, 885, 895, 905, 915, 955, 965, 975, 985, 995, 1005, 1015, 1025, 1035, 1045, 1055, 1065, 1075, 1085, 1095, 1105, 1115, 1125, 1135, 1145, 1155, 1165, 1175, 1195, 1215, 1225, 1235, 1245, 1255, 1265, 1285, 1295, 1305, 1315, 1325, 1335, 1355, 1375, 1385, 1395, 1405, 1415, 1425, 1435, 1445, 1455, 1465, 1475, 1485, 1495, 1505, 1525, 1535, 1545, 1555, 1565, 1575, 1585, 1595, 1605, 1615, 1625, 1635, 1645, 1655, 1665, 1675, 1685, 1695, 1705, 1715, 1725, 1735, 1745, 1755, 1765, 1775, 1785, 1795, 1805, 1825, 1835, 1845, 1855, 1865, 1875, 1885, 1895, 1905, 1925, 1935, 1945, 1955, 1965, 1975, 1985, 1995, 2005, 2015, 2025, 2035, 2085, 2095, 2105, 2115, 2125, 2135, 2145, 2155, 2165, 2175, 2205, 2215, 2225, 2235, 2275, 2285, 2295, 2305, 2315, 2335, 2355, 2385, 2405, 2415, 2425, 2435, 2445, 2455, 2465, 2485, 2505, 2515, 2525, 2535, 2545, 2555, 2565, 2575, 2585, 2595, 2605, 2625, 2635, 2645, 2655, 2665, 2675, 2685, 2695, 2705, 2715, 2735, 2745, 2765, 2775, 2785, 2795, 2805, 2815, 2825, 2835, 2845, 2855, 2865, 2875, 2885, 2895, 2905, 2915, 2925, 2935, 2945, 2955, 2965, 2975, 2985, 2995, 3005, 3025, 3035, 3045, 3055, 3065, 3075, 3085, 3095, 3115, 3125, 3135, 3145, 3155, 3165, 3175, 3185, 3195, 3205, 3215, 3225, 3235, 3245, 3255, 3265, 3275, 3285, 3295, 3305, 3315, 3325, 3335, 3345, 3355, 3365, 3375, 3385, 3395, 3405, 3415, 3425, 3435, 3445, 3455, 3465, 3475, 3485, 3495, 3505, 3515, 3525, 3535, 3545, 3555, 3565, 3575, 3585, 3595, 3605, 3615, 3625, 3645, 3655, 3665, 3675, 3685, 3695, 3705, 3715, 3725, 3735, 3745, 3755, 3765, 3775, 3785, 3795, 3815, 3825, 3835, 3845, 3855, 3865, 3875, 3885, 3895, 3905, 3925, 3935, 3955, 3965, 3985, 3995, 4005, 4015, 4025, 4035, 4045, 4055, 4065, 4075, 4085, 4095, 4105, 4115, 4125, 4135, 4145, 4155, 4165, 4175, 4195, 4205, 4215, 4225, 4235, 4245, 4255, 4265, 4275, 4285, 4295, 4305, 4325, 4335, 4355, 4365, 4375, 4385, 4405, 4415, 4425, 4445, 4465, 4475, 4495, 4505, 4515, 4525, 4535, 4545, 4595, 4615, 4625, 4635, 4645, 4655, 4665, 4675, 4685, 4695, 4705, 4715, 4725, 4735, 4745, 4755, 4765, 4775, 4785, 4795, 4805, 4815, 4825, 4835, 4845, 4855, 4865, 4875, 4885, 4895, 4905, 4915, 4925, 4935, 4945, 4955, 4965, 4975, 4985, 4995, 5005, 5015, 5025, 5035, 5045, 5055, 5065, 5075, 5085, 5095, 5105, 5115, 5125, 5135, 5145, 5155, 5175, 5185, 5195, 5205, 5215, 5225, 5235, 5245, 5255, 5265, 5275, 5285, 5295, 5305, 5315, 5325, 5335, 5345, 5355, 5365, 5375, 5385, 5405, 5415, 5425, 5435, 5445, 5455, 5465, 5475, 5485, 5495, 5505, 5515, 5525, 5535, 5545, 5555, 5565, 5575, 5585, 5595, 5605, 5615, 5625, 5635, 5645, 5655, 5665, 5675, 5685, 5695, 5705, 5715, 5725, 5735, 5745, 5755, 5765, 5775, 5785, 5805, 5815, 5825, 6955, 6960],
                "volumes": [8.155, 8.155, 8.132, 8.102, 8.058, 8.02, 7.969, 7.855, 7.793, 7.738, 7.69, 7.641, 7.604, 7.572, 7.55, 7.527, 7.503, 7.485, 7.427, 7.411, 7.393, 7.38, 7.363, 7.341, 7.32, 7.292, 7.273, 7.255, 7.234, 7.156, 7.125, 7.102, 7.06, 7.041, 7.021, 6.993, 6.984, 6.971, 6.962, 6.957, 6.949, 6.94, 6.926, 6.919, 6.911, 6.899, 6.891, 6.882, 6.854, 6.843, 6.836, 6.83, 6.819, 6.807, 6.796, 6.784, 6.773, 6.761, 6.755, 6.746, 6.738, 6.727, 6.72, 6.714, 6.706, 6.699, 6.693, 6.684, 6.676, 6.67, 6.659, 6.643, 6.623, 6.614, 6.607, 6.596, 6.59, 6.585, 6.565, 6.561, 6.548, 6.544, 6.537, 6.527, 6.513, 6.501, 6.494, 6.489, 6.485, 6.479, 6.474, 6.471, 6.465, 6.462, 6.454, 6.448, 6.444, 6.436, 6.431, 6.419, 6.415, 6.407, 6.4, 6.396, 6.388, 6.381, 6.372, 6.369, 6.36, 6.357, 6.346, 6.341, 6.332, 6.33, 6.324, 6.321, 6.315, 6.312, 6.308, 6.303, 6.301, 6.296, 6.293, 6.288, 6.284, 6.279, 6.273, 6.265, 6.255, 6.248, 6.244, 6.238, 6.23, 6.228, 6.22, 6.215, 6.209, 6.195, 6.19, 6.181, 6.175, 6.168, 6.163, 6.155, 6.151, 6.144, 6.139, 6.132, 6.127, 6.107, 6.102, 6.099, 6.092, 6.088, 6.083, 6.08, 6.075, 6.065, 6.061, 6.046, 6.04, 6.031, 6.027, 6.003, 5.994, 5.99, 5.984, 5.979, 5.965, 5.957, 5.939, 5.931, 5.925, 5.921, 5.918, 5.911, 5.907, 5.901, 5.893, 5.883, 5.879, 5.872, 5.868, 5.865, 5.855, 5.85, 5.846, 5.838, 5.833, 5.829, 5.813, 5.809, 5.803, 5.798, 5.79, 5.785, 5.778, 5.77, 5.767, 5.761, 5.747, 5.746, 5.734, 5.73, 5.724, 5.719, 5.716, 5.708, 5.702, 5.7, 5.695, 5.689, 5.684, 5.68, 5.675, 5.671, 5.662, 5.656, 5.653, 5.647, 5.639, 5.634, 5.63, 5.622, 5.619, 5.612, 5.603, 5.595, 5.589, 5.58, 5.576, 5.57, 5.566, 5.561, 5.557, 5.551, 5.545, 5.54, 5.536, 5.528, 5.525, 5.519, 5.514, 5.508, 5.5, 5.495, 5.489, 5.481, 5.476, 5.467, 5.463, 5.45, 5.446, 5.438, 5.432, 5.425, 5.415, 5.409, 5.401, 5.396, 5.388, 5.383, 5.375, 5.37, 5.366, 5.364, 5.358, 5.356, 5.352, 5.347, 5.345, 5.338, 5.332, 5.327, 5.324, 5.313, 5.309, 5.303, 5.295, 5.291, 5.274, 5.267, 5.257, 5.249, 5.242, 5.234, 5.227, 5.215, 5.204, 5.197, 5.192, 5.185, 5.181, 5.174, 5.168, 5.163, 5.157, 5.152, 5.144, 5.135, 5.128, 5.118, 5.112, 5.094, 5.08, 5.065, 5.056, 5.051, 5.045, 5.042, 5.034, 5.029, 5.019, 5.013, 5.007, 4.997, 4.994, 4.986, 4.978, 4.972, 4.963, 4.956, 4.936, 4.919, 4.911, 4.896, 4.883, 4.873, 4.866, 4.856, 4.852, 4.846, 4.844, 4.84, 4.838, 4.833, 4.83, 4.826, 4.82, 4.817, 4.811, 4.809, 4.801, 4.796, 4.786, 4.78, 4.766, 4.745, 4.723, 4.695, 4.687, 4.669, 4.663, 4.647, 4.639, 4.621, 4.613, 4.606, 4.594, 4.58, 4.575, 4.559, 4.55, 4.544, 4.54, 4.531, 4.525, 4.48, 4.458, 4.445, 4.431, 4.412, 4.396, 4.381, 4.361, 4.345, 4.335, 4.317, 4.291, 4.274, 4.252, 4.227, 4.198, 4.173, 4.142, 4.12, 4.093, 4.054, 4.025, 3.997, 3.956, 3.918, 3.879, 3.835, 3.775, 3.718, 3.662, 3.6, 3.541, 3.48, 3.418, 3.376, 3.324, 3.274, 3.221, 3.175, 3.142, 3.1, 3.052, 3.01, 2.96, 2.918, 2.872, 2.835, 2.791, 2.75, 2.712, 2.673, 2.639, 2.603, 2.548, 2.506, 2.455, 2.335, 2.279, 2.209, 2.141, 2.07, 1.994, 1.927, 1.846, 1.766, 1.689, 1.632, 1.565, 1.502, 1.434, 1.375, 1.318, 1.254, 1.204, 1.151, 1.097, 1.056, 1.005, 0.915, 0.868, 0.832, 0.792, 0.748, 0.711, 0.675, 0.638, 0.599, 0.563, 0.518, 0.492, 0.468, 0.436, 0.39, 0.359, 0.341, 0.319, 0.288, 0.266, 0.235, 0.211, 0.197, 0.181, 0.156, 0.137, 0.12, 0.106, 0.087, 0.075, 0.057, 0.048, 0.037, 0.027, 0.019, 0.014, 0.012, 0.008, 0.003, 0.001, 0.001, 0, 0, 0],
                "monaco_dvh_mean_dose": 3752.2,
                "monaco_dvh_max_dose":5810.4,
                "monaco_dvh_min_dose":391.9,
                "monaco_dvh_volume": 8.155

            },
            "PTV50": {
                "doses":[0, 3555, 3585, 3595, 3605, 3615, 3625, 3635, 3655, 3665, 3675, 3685, 3705, 3715, 3725, 3735, 3745, 3755, 3775, 3785, 3795, 3805, 3815, 3825, 3835, 3855, 3875, 3885, 3895, 3905, 3915, 3925, 3945, 3955, 3965, 3975, 3985, 3995, 4005, 4015, 4025, 4045, 4055, 4065, 4075, 4085, 4095, 4105, 4115, 4125, 4135, 4145, 4155, 4165, 4175, 4185, 4205, 4215, 4225, 4235, 4245, 4255, 4265, 4275, 4285, 4295, 4305, 4315, 4325, 4335, 4345, 4355, 4365, 4375, 4385, 4395, 4405, 4415, 4425, 4435, 4445, 4455, 4465, 4475, 4485, 4495, 4505, 4515, 4525, 4535, 4545, 4555, 4565, 4575, 4585, 4595, 4605, 4615, 4625, 4635, 4645, 4655, 4665, 4675, 4685, 4695, 4705, 4715, 4725, 4735, 4745, 4755, 4765, 4775, 4785, 4795, 4805, 4815, 4825, 4835, 4845, 4855, 4865, 4875, 4885, 4895, 4905, 4915, 4925, 4935, 4945, 4955, 4965, 4975, 4985, 4995, 5005, 5015, 5025, 5035, 5045, 5055, 5065, 5075, 5085, 5095, 5105, 5115, 5125, 5135, 5145, 5155, 5165, 5175, 5185, 5195, 5205, 5215, 5225, 5235, 5245, 5255, 5265, 5275, 5285, 5295, 5305, 5315, 5325, 5335, 5345, 5355, 5365, 5375, 5385, 5395, 5405, 5415, 5425, 5435, 5445, 5455, 5465, 5475, 5485, 5495, 5505, 5515, 5525, 5535, 5545, 5555, 5565, 5575, 5585, 5595, 5605, 5615, 5625, 5635, 5645, 5655, 5665, 5675, 5685, 5695, 5705, 5715, 5725, 5735, 5745, 5755, 5765, 5775, 5785, 5795, 5805, 5815, 5825, 5835, 5845, 5855, 5865, 5875, 5885, 5895, 5905, 5915, 5935, 5945, 5955, 5965, 5975, 5985, 5995, 6005, 6015, 6025, 6035, 6045, 6055, 6065, 6075, 6085, 6095, 6105, 6115, 6125, 6135, 6145, 6155, 6165, 6175, 6185, 6195, 6205, 6215, 6225, 6235, 6245, 6255, 6275, 6285, 6295, 6305, 6315, 6325, 6335, 6345, 6355, 6365, 6375, 6385, 6395, 6405, 6415, 6425, 6435, 6445, 6455, 6465, 6475, 6495, 6505, 6515, 6525, 6535, 6545, 6555, 6565, 6575, 6585, 6595, 6615, 6625, 6635, 6645, 6655, 6665, 6675, 6685, 6705, 6715, 6725, 6735, 6745, 6755, 6765, 6775, 6785, 6795, 6805, 6835, 6845, 6855, 6865, 6875, 6885, 6895, 6915, 6925, 6955, 6960],
                "volumes":[503.55, 503.55, 503.547, 503.547, 503.546, 503.546, 503.544, 503.543, 503.539, 503.538, 503.536, 503.535, 503.531, 503.527, 503.524, 503.524, 503.519, 503.516, 503.506, 503.504, 503.501, 503.496, 503.494, 503.488, 503.483, 503.475, 503.463, 503.456, 503.447, 503.444, 503.437, 503.431, 503.415, 503.403, 503.396, 503.39, 503.382, 503.372, 503.361, 503.351, 503.339, 503.313, 503.297, 503.28, 503.268, 503.252, 503.232, 503.219, 503.202, 503.182, 503.161, 503.142, 503.122, 503.095, 503.078, 503.055, 502.993, 502.965, 502.931, 502.89, 502.853, 502.824, 502.786, 502.742, 502.705, 502.658, 502.606, 502.549, 502.507, 502.47, 502.426, 502.364, 502.296, 502.215, 502.123, 502.021, 501.926, 501.812, 501.693, 501.572, 501.409, 501.259, 501.071, 500.901, 500.701, 500.509, 500.289, 500.082, 499.841, 499.631, 499.414, 499.155, 498.892, 498.602, 498.303, 498.013, 497.719, 497.379, 497.034, 496.671, 496.275, 495.834, 495.359, 494.892, 494.405, 493.9, 493.358, 492.778, 492.147, 491.507, 490.822, 490.076, 489.288, 488.457, 487.645, 486.765, 485.826, 484.908, 483.894, 482.79, 481.635, 480.475, 479.222, 477.921, 476.512, 475.076, 473.488, 471.788, 470, 468.173, 466.216, 464.019, 461.764, 459.476, 456.935, 454.375, 451.576, 448.685, 445.574, 442.376, 438.931, 435.272, 431.381, 427.266, 422.727, 417.732, 412.308, 406.508, 399.991, 393.073, 385.506, 377.4, 368.671, 359.176, 349.297, 339.141, 328.753, 317.937, 306.855, 295.682, 284.517, 273.104, 261.631, 250.185, 238.529, 227.263, 215.981, 205.16, 194.649, 184.384, 174.428, 164.929, 155.956, 147.426, 139.562, 132.239, 125.344, 118.648, 112.3, 106.306, 100.578, 95.438, 90.599, 85.996, 81.76, 77.718, 73.767, 70.076, 66.49, 62.922, 59.532, 56.333, 53.35, 50.513, 47.901, 45.409, 43.069, 40.826, 38.709, 36.767, 34.888, 33.286, 31.767, 30.349, 29.07, 27.846, 26.646, 25.562, 24.474, 23.416, 22.406, 21.452, 20.429, 19.51, 18.606, 17.767, 16.964, 16.129, 15.335, 14.598, 13.852, 13.165, 12.461, 11.826, 11.222, 10.7, 10.134, 9.664, 8.738, 8.28, 7.828, 7.411, 7.026, 6.634, 6.272, 5.954, 5.658, 5.351, 5.051, 4.745, 4.463, 4.212, 3.977, 3.756, 3.523, 3.311, 3.13, 2.963, 2.815, 2.692, 2.58, 2.467, 2.359, 2.269, 2.182, 2.09, 2.008, 1.925, 1.834, 1.742, 1.655, 1.505, 1.426, 1.36, 1.284, 1.221, 1.168, 1.101, 1.028, 0.964, 0.918, 0.879, 0.841, 0.795, 0.762, 0.727, 0.691, 0.665, 0.634, 0.614, 0.587, 0.557, 0.517, 0.496, 0.469, 0.449, 0.42, 0.406, 0.379, 0.363, 0.351, 0.327, 0.308, 0.272, 0.258, 0.236, 0.216, 0.192, 0.173, 0.159, 0.142, 0.114, 0.103, 0.097, 0.085, 0.07, 0.061, 0.057, 0.055, 0.048, 0.038, 0.031, 0.019, 0.017, 0.012, 0.01, 0.01, 0.006, 0.005, 0.005, 0.002, 0.002, 0],
                "monaco_dvh_mean_dose": 5277.2,
                "monaco_dvh_max_dose": 6959.8,
                "monaco_dvh_min_dose": 3552.2,
                "monaco_dvh_volume": 503.55,
            },
            "prv cord": {

                "doses": [0, 5, 15, 25, 35, 45, 55, 65, 75, 85, 95, 105, 115, 125, 135, 145, 155, 165, 175, 185, 195, 205, 215, 225, 235, 245, 255, 265, 275, 285, 295, 305, 315, 325, 335, 345, 355, 365, 375, 385, 395, 405, 415, 425, 435, 445, 455, 465, 475, 485, 495, 505, 515, 525, 535, 545, 555, 565, 575, 585, 595, 605, 615, 625, 635, 645, 655, 665, 675, 685, 695, 705, 715, 725, 735, 745, 755, 765, 775, 785, 795, 805, 815, 825, 835, 845, 855, 865, 875, 885, 895, 905, 915, 925, 935, 945, 955, 965, 975, 985, 995, 1005, 1015, 1025, 1035, 1045, 1055, 1065, 1075, 1085, 1095, 1105, 1115, 1125, 1135, 1145, 1155, 1165, 1175, 1185, 1195, 1205, 1215, 1225, 1235, 1245, 1255, 1265, 1275, 1285, 1295, 1305, 1315, 1325, 1335, 1345, 1355, 1365, 1375, 1385, 1395, 1405, 1415, 1425, 1435, 1445, 1455, 1465, 1475, 1485, 1495, 1505, 1515, 1525, 1535, 1545, 1555, 1565, 1575, 1585, 1595, 1605, 1625, 1635, 1645, 1655, 1665, 1675, 1685, 1695, 1705, 1715, 1725, 1735, 1745, 1755, 1765, 1775, 1785, 1795, 1805, 1815, 1825, 1835, 1845, 1855, 1865, 1875, 1885, 1895, 1905, 1915, 1925, 1935, 1945, 1955, 1965, 1975, 1985, 1995, 2005, 2015, 2025, 2035, 2045, 2065, 2075, 2085, 2095, 2105, 2115, 2125, 2135, 2145, 2155, 2165, 2175, 2185, 2195, 2205, 2215, 2225, 2235, 2245, 2255, 2265, 2275, 2285, 2295, 2305, 2315, 2325, 2335, 2345, 2355, 2365, 2375, 2385, 2395, 2405, 2425, 2435, 2445, 2465, 2475, 2485, 2495, 2505, 2515, 2525, 2535, 2545, 2555, 2565, 2575, 2585, 2595, 2605, 2615, 2625, 2635, 2655, 2665, 2685, 2695, 2705, 2715, 2725, 2735, 2745, 2755, 2765, 2775, 2785, 2795, 2805, 2835, 2845, 2855, 2865, 2885, 2895, 6955, 6960],
                "volumes" : [202.215, 202.215, 185.281, 178.426, 171.883, 166.421, 162.144, 157.958, 154.472, 151.367, 148.431, 145.753, 143.439, 141.707, 140.066, 138.441, 136.694, 135.114, 133.489, 131.856, 129.909, 127.67, 124.556, 121.016, 117.495, 113.781, 110.265, 107.293, 104.206, 101.475, 98.956, 96.835, 95.416, 94.425, 93.538, 92.733, 91.921, 91.097, 90.15, 88.896, 87.359, 85.697, 83.861, 81.868, 79.835, 77.708, 75.325, 72.962, 70.615, 68.584, 66.794, 65.322, 63.94, 62.758, 61.605, 60.413, 59.285, 58.128, 57.042, 55.941, 55, 54.143, 53.374, 52.683, 51.949, 51.262, 50.66, 50.156, 49.664, 49.189, 48.707, 48.205, 47.698, 47.239, 46.783, 46.353, 45.919, 45.523, 45.088, 44.702, 44.364, 44.045, 43.729, 43.462, 43.205, 42.962, 42.736, 42.508, 42.301, 42.107, 41.9, 41.728, 41.535, 41.366, 41.178, 41.005, 40.827, 40.621, 40.423, 40.224, 40.008, 39.794, 39.567, 39.353, 39.114, 38.882, 38.646, 38.408, 38.118, 37.882, 37.568, 37.307, 37.045, 36.732, 36.432, 36.127, 35.824, 35.502, 35.141, 34.793, 34.446, 34.062, 33.688, 33.277, 32.875, 32.393, 31.967, 31.485, 31.006, 30.481, 29.97, 29.379, 28.812, 28.202, 27.566, 26.877, 26.193, 25.525, 24.791, 24.072, 23.345, 22.586, 21.809, 20.975, 20.188, 19.355, 18.582, 17.762, 16.988, 16.176, 15.425, 14.745, 14.056, 13.373, 12.746, 12.11, 11.542, 10.978, 10.418, 9.902, 9.441, 8.991, 8.191, 7.822, 7.482, 7.169, 6.887, 6.598, 6.352, 6.087, 5.867, 5.65, 5.434, 5.225, 5.032, 4.862, 4.67, 4.501, 4.325, 4.172, 4.016, 3.874, 3.728, 3.602, 3.455, 3.322, 3.198, 3.082, 2.972, 2.861, 2.747, 2.644, 2.558, 2.476, 2.383, 2.298, 2.199, 2.138, 2.061, 1.989, 1.928, 1.852, 1.791, 1.734, 1.669, 1.557, 1.498, 1.45, 1.398, 1.347, 1.29, 1.251, 1.2, 1.163, 1.12, 1.072, 1.036, 1.001, 0.959, 0.921, 0.889, 0.847, 0.815, 0.782, 0.75, 0.724, 0.691, 0.666, 0.637, 0.61, 0.582, 0.553, 0.525, 0.502, 0.477, 0.456, 0.426, 0.409, 0.388, 0.372, 0.33, 0.311, 0.29, 0.256, 0.243, 0.221, 0.206, 0.197, 0.181, 0.168, 0.158, 0.143, 0.132, 0.129, 0.12, 0.112, 0.1, 0.093, 0.082, 0.072, 0.069, 0.059, 0.05, 0.04, 0.038, 0.03, 0.026, 0.025, 0.022, 0.018, 0.016, 0.013, 0.013, 0.012, 0.012, 0.009, 0.006, 0.006, 0.003, 0.002, 0.002, 0, 0, 0],
                "monaco_dvh_mean_dose": 496.7,
                "monaco_dvh_max_dose": 2889.2,
                "monaco_dvh_min_dose": 0,
                "monaco_dvh_volume": 202.215,
            }
        }

    def test_realistic_mean_dose(self):
        """test mean dose within 1cGy"""

        for struct, data in self.test_structs.items():
            dvh = DVH(data["doses"], data["volumes"])
            diff = dvh.mean_dose - data["monaco_dvh_mean_dose"]
            self.assertLessEqual(abs(diff), 1)

    def test_realistic_min_dose(self):
        """test min dose within 1cGy"""

        # min and max dose can only really hope to be within half a bin width

        for struct, data in self.test_structs.items():
            dvh = DVH(data["doses"], data["volumes"])
            diff = dvh.min_dose - data["monaco_dvh_min_dose"]
            self.assertLessEqual(abs(diff), 5.)

    def test_realistic_max_dose(self):
        """test max dose within 5cGy"""

        # min and max dose can only really hope to be within half a bin width

        for struct, data in self.test_structs.items():
            dvh = DVH(data["doses"], data["volumes"])
            diff = dvh.max_dose - data["monaco_dvh_max_dose"]
            self.assertLessEqual(abs(diff), 5.)

    def test_missing_doses(self):
        with self.assertRaises(ValueError):
            dvh = DVH(volumes=[1,2])

    def test_missing_volumes(self):
        with self.assertRaises(ValueError):
            dvh = DVH(doses=[1,2])

    def test_no_zero_dose_dif(self):
        doses = [1, 2, 3]
        volumes = [30, 0, 10]
        dvh = DVH(doses, volumes)
        self.assertEqual(dvh.mean_dose, 1.5)

    def test_no_zero_dose_cum(self):
        doses = [1, 2, 3, 4]
        volumes = [30, 30, 10, 5]
        dvh = DVH(doses, volumes)
        self.assertEqual(dvh.mean_dose, (5.*4. + 5*3 +20*2)/(5. + 5 + 20))

    def test_dmax(self):
        dvh = DVH(self.test_doses, self.test_diff_vols)
        self.assertEqual(dvh.max_dose, self.max_dose)

    def test_dmin(self):
        dvh = DVH(self.test_doses, self.test_diff_vols)
        self.assertEqual(dvh.min_dose, self.min_dose)

    def test_dmean(self):
        """TODO: Develop real worlds tests"""
        doses = [0, 1, 2, 3]
        volumes = [10, 0, 0, 10]

        dvh = DVH(doses, volumes)
        self.assertEqual(dvh.mean_dose, 1.5)

    def test_monotonic_increasing_strict(self):
        self.assertTrue(monotonic_increasing(range(4)))
        self.assertFalse(monotonic_increasing(self.test_diff_vols))

    def test_monotonic_decreasing(self):
        self.assertFalse(monotonic_decreasing(self.test_diff_vols))
        self.assertTrue(monotonic_decreasing(list(reversed(range(4)))))

    def test_diff_converted_to_cumulative(self):
        dvh = DVH(self.test_doses, self.test_diff_vols)
        self.assertAlmostEqual(dvh.cum_volumes[0], 1)

    def test_invalid_bin_count(self):
        with self.assertRaises(ValueError):
            dvh = DVH(self.test_doses[:-1], self.test_diff_vols)

    def test_invalid_bins(self):
        with self.assertRaises(ValueError):
            dvh = DVH([1,3,1], [2,4])

    def test_cumulative_to_diff(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        dvh2 = DVH(self.test_doses, dvh.diff_volumes)
        self.assertAlmostEqual(sum(dvh2.cum_volumes - dvh.cum_volumes), 0)

    def test_dose_to_volume_fraction_0(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.dose_to_volume_fraction(0), self.max_dose)

    def test_dose_to_volume_fraction_1(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.dose_to_volume_fraction(1), self.min_dose)

    def test_dose_to_volume_fraction_mid(self):
        """ A volume fraction of 0.9999999999 should give just slightly more than min dose"""
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.dose_to_volume_fraction(0.9999999999), self.min_dose, places=4)
        self.assertGreater(dvh.dose_to_volume_fraction(0.9999999999), self.min_dose)

    def test_dose_to_volume_fraction_invalid(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        with self.assertRaises(ValueError):
            dvh.dose_to_volume_fraction(100)

    def test_volume_fraction_receiving_zero_or_more_dose(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(0), 1)

    def test_volume_fraction_receiving_more_than_max_dose(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(dvh.max_dose+1), 0)

    def test_volume_fraction_receiving_dose(self):
        doses = [0, 1, 2, 3]
        volumes = [10, 0, 0, 10]
        dvh = DVH(doses, volumes)
        self.assertAlmostEqual(dvh.volume_fraction_receiving_dose(dvh.mean_dose), 0.5)

    def test_to_dict(self):
        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]

        dvh = DVH(doses, volumes)

        expected = {
            'diff_volumes': [0.0, 0.0, 0.5, 0.0, 0.5, 0.0],
            'cum_volumes': [1.0, 1.0, 1.0, 0.5, 0.5, 0.0],
            'doses': [0.0, 1.0, 2.0, 3.0, 4.0, 5.0],
            'mean_dose': 3.0,
            'max_dose': 4.0,
            'min_dose': 2.0
        }
        self.assertDictEqual(expected, dvh.to_dict())

    def test_to_dict_no_diff(self):
        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]

        dvh = DVH(doses, volumes)

        expected = {
            'cum_volumes': [1.0, 1.0, 1.0, 0.5, 0.5, 0.0],
            'doses': [0.0, 1.0, 2.0, 3.0, 4.0, 5.0],
            'mean_dose': 3.0,
            'max_dose': 4.0,
            'min_dose': 2.0
        }
        self.assertDictEqual(expected, dvh.to_dict(False))

    def test_json_serialze(self):

        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]

        dvh = DVH(doses, volumes)

        expected = {
            'diff_volumes': [0.0, 0.0, 0.5, 0.0, 0.5, 0.0],
            'cum_volumes': [1.0, 1.0, 1.0, 0.5, 0.5, 0.0],
            'doses': [0.0, 1.0, 2.0, 3.0, 4.0, 5.0],
            'mean_dose': 3.0,
            'max_dose': 4.0,
            'min_dose': 2.0
        }
        self.assertDictEqual(json.loads(json.dumps(expected)), json.loads(dvh.serialize()))

    def test_json_serialze_invalid(self):

        doses = [1, 2, 3, 4, 5]
        volumes = [1, 1, 0.5, 0.5, 0]

        dvh = DVH(doses, volumes)
        with self.assertRaises(TypeError):
            dvh.serialize(method="blah")


if __name__ == '__main__':
    unittest.main()

    def test_dose_to_volume_fraction_invalid(self):
        dvh = DVH(self.test_doses, self.test_cum_vols)
        with self.assertRaises(ValueError):
            dvh.dose_to_volume_fraction(100)

if __name__ == '__main__':
    unittest.main()
