Skip to content
Snippets Groups Projects
test_data_utils.py 24.5 KiB
Newer Older
  • Learn to ignore specific revisions
  • Pedro Magalhães's avatar
    Pedro Magalhães committed
    # imports
    
    # standard
    import random
    import math
    from statistics import mean
    
    # local, internal
    from src.topupopt.data.misc import utils
    
    class TestDataUtils:
    
        def test_profile_synching2(self):
            integration_result = 10446
            ratio_min_avg = 0.2
    
            min_max_ratio = ratio_min_avg / (2 - ratio_min_avg)
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
                2.66,
                2.34,
                3.54,
                7.42,
                11.72,
                16.94,
                17.94,
                17.98,
                14.1,
                10.48,
                6.74,
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            time_interval_durations = [
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                31,  # jan
                28,  # fev
                31,  # mar
                30,  # apr
                31,  # may
                30,  # june
                31,  # july
                31,  # august
                30,  # september
                31,  # october
                30,  # november
                31,  # december
            ]
    
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # *********************************************************************
            # *********************************************************************
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # state correlates with output
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            new_profile = utils.create_profile_using_time_weighted_state(
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                integration_result=integration_result,
    
                states=states,
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                time_interval_durations=time_interval_durations,
    
                min_max_ratio=min_max_ratio,
                states_correlate_profile=False,
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            expected_result = [
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                1500.0513102636057,
                1436.2189684321309,
                1500.0513102636044,
                1206.6051909345115,
                896.2493366213225,
                525.7218723351705,
                283.3475134825171,
                185.83058429361876,
                270.8127439165165,
                538.2566419011698,
                861.4985340132666,
                1241.355993542566,
            ]
    
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            abs_tol = 1e-3
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
    
            assert math.isclose(sum(new_profile), integration_result, abs_tol=abs_tol)
    
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            for sample, expected_sample in zip(new_profile, expected_result):
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                assert math.isclose(sample, expected_sample, abs_tol=abs_tol)
    
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # *********************************************************************
            # *********************************************************************
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # state does not correlate with output
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # state correlates with output
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            new_profile = utils.create_profile_using_time_weighted_state(
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                integration_result=integration_result,
    
                states=states,
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                time_interval_durations=time_interval_durations,
    
                min_max_ratio=min_max_ratio,
                states_correlate_profile=True,
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            expected_result = [
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                274.3377308322865,
                166.45500417060902,
                274.33773083228533,
                510.54549399699533,
                878.1397044745678,
                1191.4288125963367,
                1491.041527613374,
                1588.5584568022714,
                1446.3379410149894,
                1236.132399194721,
                855.6521509182398,
                533.0330475533233,
            ]
    
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            abs_tol = 1e-3
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
    
            assert math.isclose(sum(new_profile), integration_result, abs_tol=abs_tol)
    
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            for sample, expected_sample in zip(new_profile, expected_result):
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                assert math.isclose(sample, expected_sample, abs_tol=abs_tol)
    
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # *********************************************************************
            # *********************************************************************
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # find out the peaks of the sinusoidal profile
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            pmax, pmin = utils.max_min_sinusoidal_profile(
                integration_result=integration_result,
                period=sum(time_interval_durations),
                time_interval_duration=mean(time_interval_durations),
    
                min_max_ratio=min_max_ratio,
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            expected_pmax, expected_pmin = 1558.972133279683, 182.02786672031687
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
    
            assert math.isclose(pmax, expected_pmax, abs_tol=1e-3)
    
            assert math.isclose(pmin, expected_pmin, abs_tol=1e-3)
    
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # *********************************************************************
            # *********************************************************************
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # raise exception
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            error_triggered = False
            time_interval_durations.pop(0)
            try:
                new_profile = utils.create_profile_using_time_weighted_state(
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                    integration_result=integration_result,
    
                    states=states,
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                    time_interval_durations=time_interval_durations,
    
                    min_max_ratio=min_max_ratio,
                    states_correlate_profile=True,
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            except ValueError:
                error_triggered = True
            assert error_triggered
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # *********************************************************************
            # *********************************************************************
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
        # *************************************************************************
        # *************************************************************************
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
        def test_profile_synching(self):
            # synch, normal, ex1
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
    
            profile = [1, 2, 3, 4]
            reference_profile = [2, 3, 4, 1]
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            synched_profile = utils.synch_profile(profile, reference_profile)
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
            true_synched_profile = [2, 3, 4, 1]
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            assert repr(synched_profile) == repr(true_synched_profile)
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # synch, normal, ex2
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
    
            profile = [-2, -1, 1, 2, 0]
            reference_profile = [2, 3, 4, 1, 5]
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            synched_profile = utils.synch_profile(profile, reference_profile)
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
            true_synched_profile = [-1, 0, 1, -2, 2]
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            assert repr(synched_profile) == repr(true_synched_profile)
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # synch, alternative, ex1
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
    
            profile = [1, 2, 3, 4]
            reference_profile = [2, 3, 4, 1]
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            synched_profile = utils.synch_profile(profile, reference_profile, synch=False)
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
            true_synched_profile = [3, 2, 1, 4]
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            assert repr(synched_profile) == repr(true_synched_profile)
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
        # *************************************************************************
        # *************************************************************************
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
        def test_profile_generation(self):
            # *********************************************************************
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # fixed time interval durations
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            number_tests = 10
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            for test_index in range(number_tests):
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                integration_period = 365 * 24 * 3600
    
                number_intervals = random.randint(1, 8760)
    
                phase_shift_radians = 2 * math.pi * random.random()
    
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
                time_interval_durations = [
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                    round(integration_period / number_intervals)
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
                    for i in range(number_intervals)
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
                integration_result = 100
    
                min_max_ratio = 0.2
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
                profile = utils.discrete_sinusoid_matching_integral(
                    integration_result,
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                    time_interval_durations,
    
                    min_max_ratio,
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                    phase_shift_radians=phase_shift_radians,
                )
    
                assert math.isclose(sum(profile), integration_result, abs_tol=0.01)
    
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # *********************************************************************
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # import matplotlib.pyplot as plt
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # # Data for plotting
            # x = [i for i in range(number_intervals)]
            # y = profile
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # fig, ax = plt.subplots()
            # ax.plot(x, y)
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # ax.set(xlabel='time (s)', ylabel='voltage (mV)',
            #         title='About as simple as it gets, folks')
            # ax.grid()
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # #fig.savefig("test.png")
            # plt.show()
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # *********************************************************************
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # variable time step durations
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            number_tests = 10
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            for test_index in range(number_tests):
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                number_intervals = random.randint(10, 8760)
    
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
                time_interval_durations = [
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                    random.random() * 3.6e3 for i in range(number_intervals)
                ]
    
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
                integration_period = sum(time_interval_durations)
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
    
                phase_shift_radians = 2 * math.pi * random.random()
    
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
                integration_result = 100
    
                min_max_ratio = 0.2
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
                profile = utils.discrete_sinusoid_matching_integral(
                    integration_result,
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                    time_interval_durations,
    
                    min_max_ratio,
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                    phase_shift_radians=phase_shift_radians,
                )
    
                assert math.isclose(sum(profile), integration_result, abs_tol=0.01)
    
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # *********************************************************************
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # # import matplotlib.pyplot as plt
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # t = [sum(time_interval_durations[0:i])
            #      for i in range(len(time_interval_durations)+1)]
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # # Data for plotting
            # x = [(t[i+1]+t[i])*0.5
            #      for i in range(number_intervals)] # time interval's center point
            # y = profile
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # fig, ax = plt.subplots()
            # ax.plot(x, y)
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # ax.set(xlabel='time (s)', ylabel='voltage (mV)',
            #         title='About as simple as it gets, folks')
            # ax.grid()
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # #fig.savefig("test.png")
            # plt.show()
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # *********************************************************************
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # use the default phase shift
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
    
            integration_period = 365 * 24 * 3600
    
            number_intervals = random.randint(1, 8760)
    
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            time_interval_durations = [
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                round(integration_period / number_intervals)
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
                for i in range(number_intervals)
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            integration_result = 100
    
            min_max_ratio = 0.2
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            profile = utils.discrete_sinusoid_matching_integral(
    
                integration_result, time_interval_durations, min_max_ratio
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
            )
    
            assert math.isclose(sum(profile), integration_result, abs_tol=0.01)
    
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
        # *************************************************************************
        # *************************************************************************
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
        def test_key_generation(self):
            # generate_pseudo_unique_key
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            key_list = (str(random.random()) for i in range(10))
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            new_key = utils.generate_pseudo_unique_key(key_list=key_list)
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            assert new_key not in key_list
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # use an empty key list
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            new_key = utils.generate_pseudo_unique_key(key_list=[])
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            assert new_key not in key_list
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # use zero iterations to force an error
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            error_triggered = False
            try:
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
                new_key = utils.generate_pseudo_unique_key(
                    key_list=key_list, max_iterations=0
                )
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            except Exception:
                error_triggered = True
            assert error_triggered
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            # use a seed number to trigger more iterations
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            import uuid
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            rand = random.Random()
            rand.seed(360)
            uuid.uuid4 = lambda: uuid.UUID(int=rand.getrandbits(128), version=4)
    
    Pedro L. Magalhães's avatar
    Pedro L. Magalhães committed
    
            key_list = [
                "3e225573-4e78-48c8-bb08-efbeeb795c22",
                "f6d30428-15d1-41e9-a952-0742eaaa5a31",
                "8c29b906-2518-41c5-ada8-07b83508b5b8",
                "f9a72a39-1422-4a02-af97-906ce79c32a3",
                "b6941a48-10cc-465d-bf53-178bd2939bd1",
            ]
    
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            new_key = utils.generate_pseudo_unique_key(key_list=key_list)
    
    Pedro Magalhães's avatar
    Pedro Magalhães committed
            assert new_key not in key_list
    
    
        # *************************************************************************
        # *************************************************************************
        
        def test_state_correlated_profile(self):
            
            # correlation: direct, inverse
            # states: positive, negative
            # time intervals: regular irregular
            # 
            
            # profile with positive correlation, positive states, regular intervals
            number_time_intervals = 10
            states = [i+1 for i in range(number_time_intervals)]
            integration_result = 100
            time_interval_durations = [10 for i in range(number_time_intervals)]
            states_correlate_profile = True
            min_max_ratio = 0.2
            
    
            profile, a, b = utils.generate_state_correlated_profile(
    
                integration_result=integration_result, 
                states=states, 
                time_interval_durations=time_interval_durations, 
                states_correlate_profile=states_correlate_profile, 
                min_max_ratio=min_max_ratio, 
                solver='glpk'
                )
            
            # test profile 
    
            assert a > 0 and b > 0
    
            assert len(profile) == number_time_intervals
            assert math.isclose(sum(profile), integration_result, abs_tol=1e-3)
            assert math.isclose(min(profile), max(profile)*min_max_ratio, abs_tol=1e-3)
            assert max(profile) == profile[number_time_intervals-1]
            
            # profile with inverse correlation, positive states, regular intervals
            number_time_intervals = 10
            states = [i+1 for i in range(number_time_intervals)]
            integration_result = 100
            time_interval_durations = [10 for i in range(number_time_intervals)]
            states_correlate_profile = False
            min_max_ratio = 0.2
            
    
            profile, a, b = utils.generate_state_correlated_profile(
    
                integration_result=integration_result, 
                states=states, 
                time_interval_durations=time_interval_durations, 
                states_correlate_profile=states_correlate_profile, 
                min_max_ratio=min_max_ratio, 
                solver='glpk'
                )
            
            # test profile 
    
            assert a < 0 and b > 0
    
            assert len(profile) == number_time_intervals
            assert math.isclose(sum(profile), integration_result, abs_tol=1e-3)
            assert math.isclose(min(profile), max(profile)*min_max_ratio, abs_tol=1e-3)
            assert min(profile) == profile[number_time_intervals-1]
            
    
        # *************************************************************************
        # *************************************************************************
            
        def test_trigger_state_correlated_profile_error(self):
            
            # trigger an error
            number_time_intervals = 10
            states = [i+1 for i in range(number_time_intervals)]
            integration_result = 100
            time_interval_durations = [10 for i in range(number_time_intervals+1)]
            states_correlate_profile = True
            min_max_ratio = 0.2
            
            error_raised = False
            try:
                utils.generate_state_correlated_profile(
                    integration_result=integration_result, 
                    states=states, 
                    time_interval_durations=time_interval_durations, 
                    states_correlate_profile=states_correlate_profile, 
                    min_max_ratio=min_max_ratio, 
                    solver='glpk'
                    )
            except ValueError:
                error_raised = True
            assert error_raised
        
        # *************************************************************************
        # *************************************************************************
        
        def test_manual_state_correlated_profile(self):
            
            # correlation: direct, inverse
            # states: positive, negative
            # time intervals: regular irregular
            
            # profile with positive correlation, positive states, regular intervals
            number_time_intervals = 10
            states = [i+1 for i in range(number_time_intervals)]
            integration_result = 100
            time_interval_durations = [10 for i in range(number_time_intervals)]
            deviation_gain = 1
            
            profile = utils.generate_manual_state_correlated_profile(
                integration_result=integration_result, 
                states=states, 
                time_interval_durations=time_interval_durations, 
                deviation_gain=deviation_gain
                )
            
            # test profile 
            assert len(profile) == number_time_intervals
            assert math.isclose(sum(profile), integration_result, abs_tol=1e-3)
            assert max(profile) == profile[number_time_intervals-1]
            
            # profile with inverse correlation, positive states, regular intervals
            number_time_intervals = 10
            states = [i+1 for i in range(number_time_intervals)]
            integration_result = 100
            time_interval_durations = [10 for i in range(number_time_intervals)]
            deviation_gain = -1
            
            profile = utils.generate_manual_state_correlated_profile(
                integration_result=integration_result, 
                states=states, 
                time_interval_durations=time_interval_durations, 
                deviation_gain=deviation_gain
                )
            
            # test profile 
            assert len(profile) == number_time_intervals
            assert math.isclose(sum(profile), integration_result, abs_tol=1e-3)
            assert min(profile) == profile[number_time_intervals-1]
    
        # *************************************************************************
        # *************************************************************************
            
        def test_trigger_manual_state_correlated_profile_error(self):
            
            # trigger an error
            number_time_intervals = 10
            states = [i+1 for i in range(number_time_intervals)]
            integration_result = 100
            time_interval_durations = [10 for i in range(number_time_intervals+1)]
            deviation_gain = -1
            
            error_raised = False
            try:
                utils.generate_manual_state_correlated_profile(
                    integration_result=integration_result, 
                    states=states, 
                    time_interval_durations=time_interval_durations, 
                    deviation_gain=deviation_gain
                    )
            except ValueError:
                error_raised = True
            assert error_raised
    
        # *************************************************************************
        # *************************************************************************
    
        
        def test_create_profile_sinusoidal(self):
            
            number_intervals = 10
            integration_result = 100
            min_max_ratio = 0.25
            
            # sinusoidal profile
            
            profile = utils.generate_profile(
                integration_result=integration_result, 
                time_interval_durations=[1 for i in range(number_intervals)], 
                min_max_ratio=min_max_ratio, 
                )
            
            assert len(profile) == number_intervals
            assert math.isclose(sum(profile), integration_result, abs_tol=1e-3)
            
            # sinusoidal profile with phase shift
            
            profile = utils.generate_profile(
                integration_result=integration_result, 
                time_interval_durations=[1 for i in range(number_intervals)], 
                min_max_ratio=min_max_ratio, 
                phase_shift_radians=math.pi/2
                )
            
            assert len(profile) == number_intervals
            assert math.isclose(sum(profile), integration_result, abs_tol=1e-3)
            
            # use incorrect parameter
            
            error_raised = False
            try:
                profile = utils.generate_profile(
                    integration_result=integration_result, 
                    time_interval_durations=[1 for i in range(number_intervals)], 
                    min_max_ratio=min_max_ratio, 
                    deviation_gain=-1,
                    )
            except TypeError:
                error_raised = True
            assert error_raised
    
        # *************************************************************************
        # *************************************************************************
            
        def test_create_profile_predefined_gain(self):
            
            number_intervals = 10
            integration_result = 100
            deviation_gain = 5
            states = [number_intervals-i*0.5 for i in range(number_intervals)]
            
            # predefined gain
            
            profile = utils.generate_profile(
                integration_result=integration_result, 
                time_interval_durations=[1 for i in range(number_intervals)], 
                states=states, 
                deviation_gain=deviation_gain
                )
            
            assert len(profile) == number_intervals
            assert math.isclose(sum(profile), integration_result, abs_tol=1e-3)      
            
            # predefined gain, opposite sign
            
            profile = utils.generate_profile(
                integration_result=integration_result, 
                time_interval_durations=[1 for i in range(number_intervals)], 
                states=states, 
                deviation_gain=-deviation_gain
                )
            
            assert len(profile) == number_intervals
            assert math.isclose(sum(profile), integration_result, abs_tol=1e-3)    
            
            # use incorrect parameter
            
            error_raised = False
            try:
                profile = utils.generate_profile(
                    integration_result=integration_result, 
                    time_interval_durations=[1 for i in range(number_intervals)], 
                    states=states, 
                    deviation_gain=-deviation_gain,
                    phase_shift_radians=math.pi
                    )
            except TypeError:
                error_raised = True
            assert error_raised
    
        # *************************************************************************
        # *************************************************************************
            
        def test_create_profile_via_sorting_sinusoid(self):
            
            number_intervals = 10
            integration_result = 100
            states_correlate_profile = True
            min_max_ratio = 0.25
            states = [number_intervals-i*0.5 for i in range(number_intervals)]
            
            # sorting and sinusoidal function        
            profile = utils.generate_profile(
                integration_result=integration_result, 
                time_interval_durations=[1 for i in range(number_intervals)], 
                min_max_ratio=min_max_ratio, 
                states=states, 
                states_correlate_profile=states_correlate_profile, 
                )
            
            assert len(profile) == number_intervals
            assert math.isclose(sum(profile), integration_result, abs_tol=1e-3)    
            
    
        # *************************************************************************
        # *************************************************************************
            
        def test_create_profile_via_optimisation(self):
            
            number_intervals = 10
            integration_result = 100
            states_correlate_profile = True
            min_max_ratio = 0.25
            solver = 'glpk'
            states = [number_intervals-i*0.5 for i in range(number_intervals)]
            
            # optimisation
            
            # states_correlate_profile is necessary
            # min_max_ratio is necessary
            # solver is necessary
            # states matter but the gain must be determined
            
            profile = utils.generate_profile(
                integration_result=integration_result, 
                time_interval_durations=[1 for i in range(number_intervals)], 
                min_max_ratio=min_max_ratio, 
                states=states, 
                states_correlate_profile=states_correlate_profile, 
                solver=solver
                )
            
            assert len(profile) == number_intervals
            assert math.isclose(sum(profile), integration_result, abs_tol=1e-3)    
            assert math.isclose(min(profile),max(profile)*min_max_ratio, abs_tol=1e-3)
            
            # optimisation but with states that do no warrant it
            states = [5 for i in range(number_intervals)]
            
            profile = utils.generate_profile(
                integration_result=integration_result, 
                time_interval_durations=[1 for i in range(number_intervals)], 
                min_max_ratio=min_max_ratio, 
                states=states, 
                states_correlate_profile=states_correlate_profile, 
                solver=solver
                )
            
            assert len(profile) == number_intervals
            assert math.isclose(sum(profile), integration_result, abs_tol=1e-3)   
            # the min to max ratio cannot be observed if the states do not change
            assert math.isclose(min(profile), max(profile), abs_tol=1e-3)
            
            # use incorrect parameter
            error_raised = False
            try:
                profile = utils.generate_profile(
                    integration_result=integration_result, 
                    time_interval_durations=[1 for i in range(number_intervals)], 
                    min_max_ratio=min_max_ratio, 
                    states=states, 
                    states_correlate_profile=states_correlate_profile, 
                    solver=solver,
                    phase_shift_radians=math.pi
                    )
            except TypeError:
                error_raised = True
            assert error_raised
            
        # *************************************************************************
        # *************************************************************************
    
    # *****************************************************************************
    
    # *****************************************************************************