def test_get_doc(self): setup_test() def getdocl(objtype, obj, name, encoding=None): global directive inst = DispatcherDirective._registry[objtype](directive, 'tmp') inst.objpath = [name] inst.object = obj ds = inst.get_doc(encoding) # for testing purposes, concat them and strip the empty line at the end res = sum(ds, [])[:-1] return res # objects without docstring dsp_local = Dispatcher() self.assertEqual(getdocl('dispatcher', dsp_local, 'dsp_local'), []) dsp_local = Dispatcher(description='Description') res = getdocl('dispatcher', dsp_local, 'dsp_local') self.assertEqual(res, ['Description']) dsp_local.__doc__ = 'First line\n\nOther\n lines' res = getdocl('dispatcher', dsp_local, 'dsp_local') self.assertEqual(res, ['First line', '', 'Other', ' lines'])
def setUp(self): ss_dsp = Dispatcher() def fun(a, c): return a + 1, c, a - 1 ss_dsp.add_function('module:fun', fun, ['a', 'e'], ['b', 'c', 'd']) ss_dsp_func = SubDispatchFunction(ss_dsp, 'func', ['e', 'a'], ['c', 'd', 'b']) sub_disfun = partial(ss_dsp_func, 5) s_dsp = Dispatcher() s_dsp.add_function('sub_dispatch', sub_disfun, ['a'], ['b', 'c', SINK]) dispatch = SubDispatch(s_dsp, ['b', 'c', 'a'], output_type='list') dsp = Dispatcher() dsp.add_data('input', default_value={'a': 3}) dsp.add_function('dispatch', dispatch, ['input'], [SINK, 'h', 'i']) dsp.dispatch(inputs={'f': 'new'}) self.dsp = dsp self.fun = fun self.sub_dispatch = sub_disfun self.s_dsp = s_dsp self.ss_dsp = ss_dsp self.ss_dsp_func = ss_dsp_func
def setUp(self): dsp = Dispatcher() dsp.add_function(function=max, inputs=['a', 'b'], outputs=['c']) dsp.add_function(function=min, inputs=['c', 'b'], outputs=['a'], input_domain=lambda c, b: c * b > 0) self.dsp_1 = dsp dsp = Dispatcher() def f(a, b): return a + b, a - b dsp.add_function(function=f, inputs=['a', 'b'], outputs=['c', SINK]) dsp.add_function(function=f, inputs=['c', 'b'], outputs=[SINK, 'd']) self.dsp_2 = dsp dsp = Dispatcher() dsp.add_function(function=f, inputs=['a', 'b'], outputs=['c', 'd'], out_weight={'d': 100}) dsp.add_dispatcher(dsp=self.dsp_1.copy(), inputs={'a': 'a', 'b': 'b'}, outputs={'c': 'd'}) self.dsp_3 = dsp dsp = Dispatcher() dsp.add_function(function=SubDispatchFunction( self.dsp_3, 'f', ['b', 'a'], ['c', 'd']), inputs=['b', 'a'], outputs=['c', 'd'], out_weight={'d': 100} ) dsp.add_dispatcher(dsp=self.dsp_1.copy(), inputs={'a': 'a', 'b': 'b'}, outputs={'c': 'd'}) self.dsp_4 = dsp
def setUp(self): ss_dsp = Dispatcher() fun = lambda a: (a + 1, 5, a - 1) dom = lambda kw: True c = '|!"£$%&/()=?^*+éè[]#¶ù§çò@:;-_.,<>' ss_dsp.add_function(function=fun, inputs=['a'], outputs=['b', SINK, c], input_domain=dom, weight=1) def raise_fun(a): raise ValueError('Error') ss_dsp.add_function(function=raise_fun, inputs=['a'], outputs=['b']) sdspfunc = SubDispatchFunction(ss_dsp, 'SubDispatchFunction', ['a'], ['b', c]) sdsppipe = SubDispatchPipe(ss_dsp, 'SubDispatchPipe', ['a'], ['b', c]) sdsp = SubDispatch(ss_dsp, ['b', c], output_type='list') s_dsp = Dispatcher() s_dsp.add_function(None, sdspfunc, ['a'], ['b', 'c'], weight=2) s_dsp.add_function(None, sdsppipe, ['a'], ['b', 'c'], out_weight={'c': 5}) s_dsp.add_function('SubDispatch', sdsp, ['d'], ['e', 'f']) dsp = Dispatcher() import numpy as np dsp.add_data('A', default_value=np.zeros(1000)) dsp.add_data('D', default_value={'a': 3}) dsp.add_dispatcher(dsp=s_dsp, inputs={ 'A': 'a', 'D': 'd' }, outputs={ 'b': 'B', 'c': 'C', 'e': 'E', 'f': 'F' }, inp_weight={'A': 3}) self.sol = dsp.dispatch() self.dsp = dsp
def setUp(self): dsp = Dispatcher() dsp.add_function(function=max, inputs=['a', 'b'], outputs=['c']) dsp.add_function(function=min, inputs=['c', 'b'], outputs=['a'], input_domain=lambda c, b: c * b > 0) self.dsp_1 = dsp dsp = Dispatcher() def f(a, b): return a + b, a - b dsp.add_function(function=f, inputs=['a', 'b'], outputs=['c', SINK]) dsp.add_function(function=f, inputs=['c', 'b'], outputs=[SINK, 'd']) self.dsp_2 = dsp
def write_outputs(): """ Defines a module to write on files the outputs of the CO2MPAS model. .. dispatcher:: dsp >>> dsp = write_outputs() :return: The write outputs module. :rtype: SubDispatchFunction """ dsp = Dispatcher( name='write_outputs', description='Writes on files the outputs of the CO2MPAS model.' ) dsp.add_function( function=partial(convert2df, data_descriptions=get_doc_description(), write_schema=define_data_schema(read=False)), inputs=['output_data', 'start_time', 'main_flags'], outputs=['dfs'] ) dsp.add_function( function=write_to_excel, inputs=['dfs', 'output_file_name', 'template_file_name'] ) inp = ['output_file_name', 'template_file_name', 'output_data', 'start_time', 'main_flags'] return dsp_utl.SubDispatchFunction(dsp, dsp.name, inp)
def report(): """ Defines and returns a function that produces a vehicle report from CO2MPAS outputs. .. dispatcher:: dsp >>> dsp = report() :return: The reporting model. :rtype: SubDispatchFunction """ # Initialize a dispatcher. dsp = Dispatcher( name='make_report', description='Produces a vehicle report from CO2MPAS outputs.' ) dsp.add_function( function=get_report_output_data, inputs=['output_data'], outputs=['report'] ) dsp.add_function( function=extract_summary, inputs=['report', 'vehicle_name'], outputs=['summary'] ) inputs = ['output_data', 'vehicle_name'] outputs = ['report', 'summary'] return dsp_utl.SubDispatchFunction(dsp, dsp.name, inputs, outputs)
def thermal(): """ Defines the engine thermal model. .. dispatcher:: dsp >>> dsp = thermal() :return: The engine thermal model. :rtype: Dispatcher """ dsp = Dispatcher(name='thermal', description='Models the engine thermal behaviour.') dsp.add_function(function=calculate_engine_temperature_derivatives, inputs=['times', 'engine_coolant_temperatures'], outputs=['engine_temperature_derivatives']) dsp.add_function(function=identify_max_engine_coolant_temperature, inputs=['engine_coolant_temperatures'], outputs=['max_engine_coolant_temperature']) dsp.add_function(function=calibrate_engine_temperature_regression_model, inputs=[ 'idle_engine_speed', 'on_engine', 'engine_temperature_derivatives', 'engine_coolant_temperatures', 'final_drive_powers_in', 'engine_speeds_out_hot', 'accelerations' ], outputs=['engine_temperature_regression_model']) dsp.add_function(function=predict_engine_coolant_temperatures, inputs=[ 'engine_temperature_regression_model', 'times', 'final_drive_powers_in', 'engine_speeds_out_hot', 'accelerations', 'initial_engine_temperature', 'max_engine_coolant_temperature' ], outputs=['engine_coolant_temperatures']) dsp.add_function(function=identify_engine_thermostat_temperature, inputs=['engine_temperature_regression_model'], outputs=['engine_thermostat_temperature']) dsp.add_function(function=identify_engine_thermostat_temperature_window, inputs=[ 'engine_thermostat_temperature', 'engine_coolant_temperatures' ], outputs=['engine_thermostat_temperature_window']) dsp.add_function(function=identify_initial_engine_temperature, inputs=['engine_coolant_temperatures'], outputs=['initial_engine_temperature']) return dsp
def test_load_map(self): save_map(self.dsp, self.tmp) dsp = Dispatcher(default_values=self.dsp.default_values) load_map(dsp, self.tmp) self.assertEqual(dsp.dmap.degree(self.fun_id), self.dsp.dmap.degree(self.fun_id)) self.assertEqual(dsp.dmap.node[self.fun_id]['function'](1), 2) self.assertEqual(dsp.dispatch()['b'], 6)
def setUp(self): sub_dsp = Dispatcher() def fun(a): return a + 1, a - 1 sub_dsp.add_function('fun', fun, ['a'], ['b', 'c']) dispatch = SubDispatch(sub_dsp, ['a', 'b', 'c']) dispatch_dict = SubDispatch(sub_dsp, ['c'], output_type='dict') dispatch_list = SubDispatch(sub_dsp, ['a', 'c'], output_type='list') dispatch_val = SubDispatch(sub_dsp, ['c'], output_type='list') dsp = Dispatcher() dsp.add_function('dispatch', dispatch, ['d'], ['e']) dsp.add_function('dispatch_dict', dispatch_dict, ['d'], ['f']) dsp.add_function('dispatch_list', dispatch_list, ['d'], ['g']) dsp.add_function('dispatch_list', dispatch_val, ['d'], ['h']) self.dsp = dsp
def test_replicate_function(self): dsp = Dispatcher() def fun(a): return a + 1, a - 1 dsp.add_function('fun', ReplicateFunction(fun), ['a', 'b'], ['c', 'd']) o = dsp.dispatch(inputs={'a': 3, 'b': 4}) self.assertEqual(o, {'a': 3, 'b': 4, 'c': (4, 2), 'd': (5, 3)})
def nedc_cycle(): """ Defines the wltp cycle model. .. dispatcher:: dsp >>> dsp = nedc_cycle() :return: The wltp cycle model. :rtype: Dispatcher """ dsp = Dispatcher( name='NEDC cycle model', description='Returns the theoretical times, velocities, and gears of ' 'NEDC.') dsp.add_data(data_id='initial_temperature', default_value=dfl.values.initial_temperature_NEDC, description='Initial temperature of the test cell [°C].') dsp.add_data(data_id='k1', default_value=dfl.values.k1) dsp.add_data(data_id='k2', default_value=dfl.values.k2) dsp.add_function(function_id='set_max_gear_as_default_k5', function=dsp_utl.bypass, inputs=['max_gear'], outputs=['k5']) dsp.add_data(data_id='k5', default_value=dfl.values.k5, initial_dist=10) dsp.add_data(data_id='time_sample_frequency', default_value=dfl.values.time_sample_frequency) dsp.add_function( function_id='nedc_gears', function=dsp_utl.add_args(nedc_gears), inputs=['gear_box_type', 'times', 'max_gear', 'k1', 'k2', 'k5'], outputs=['gears'], input_domain=lambda *args: args[0] == 'manual') dsp.add_function(function=nedc_velocities, inputs=['times', 'gear_box_type'], outputs=['velocities']) dsp.add_function(function=nedc_time_length, inputs=['time_sample_frequency'], outputs=['time_length'], weight=5) return dsp
def selector(*data): """ Defines the models' selector model. .. dispatcher:: dsp >>> dsp = selector() :return: The models' selector model. :rtype: SubDispatchFunction """ data = data or ('wltp_h', 'wltp_l') dsp = Dispatcher( name='Models selector', description='Select the calibrated models.', ) dsp.add_function(function=partial(dsp_utl.map_list, data), inputs=data, outputs=['CO2MPAS_results']) dsp.add_data(data_id='models', function=combine_outputs, wait_inputs=True) dsp.add_data(data_id='scores', function=combine_scores, wait_inputs=True) setting = sub_models() dsp.add_data(data_id='error_settings', default_value={}) m = list(setting) dsp.add_function(function=partial(split_error_settings, m), inputs=['error_settings'], outputs=['error_settings/%s' % k for k in m]) for k, v in setting.items(): v['dsp'] = v.pop('define_sub_model', define_sub_model)(**v) v['metrics'] = dsp_utl.map_list(v['targets'], *v['metrics']) dsp.add_function(function=v.pop('model_selector', _selector)(k, data, data, v), function_id='%s selector' % k, inputs=['CO2MPAS_results', 'error_settings/%s' % k], outputs=['models', 'scores']) func = dsp_utl.SubDispatchFunction(dsp=dsp, function_id='models_selector', inputs=('error_settings', ) + data, outputs=['models', 'scores']) return func
def setUp(self): ss_dsp = Dispatcher() fun = lambda a: (a + 1, 5, a - 1) c = '|!"£$%&/()=?^*+éè[]#¶ù§çò@:;-_.,<>' ss_dsp.add_function(function=fun, inputs=['a'], outputs=['b', SINK, c]) sub_dispatch = SubDispatch(ss_dsp, ['a', 'b', c], output_type='list') s_dsp = Dispatcher() s_dsp.add_function('sub_dispatch', sub_dispatch, ['a'], ['b', 'c', 'd']) dispatch = SubDispatch(s_dsp, ['b', 'c', 'd'], output_type='list') dsp = Dispatcher() dsp.add_data('input', default_value={'a': {'a': 3, 'funcs': fun}}) dsp.add_function('dispatch', dispatch, ['input'], [SINK, 'h', 'i']) dsp.dispatch() self.dsp = dsp
def setUp(self): dsp = Dispatcher() dsp.add_data('a', default_value=5) def f(a): return a + 1 self.fun_id = dsp.add_function(function=f, inputs=['a'], outputs=['b']) self.dsp = dsp self.tmp = mkstemp()[1]
def cold_start(): """ Defines the engine cold start model. .. dispatcher:: dsp >>> dsp = cold_start() :return: The engine start/stop model. :rtype: Dispatcher """ dsp = Dispatcher( name='cold_start', description='Models the engine cold start strategy.' ) dsp.add_function( function=identify_cold_start_speeds_phases, inputs=['engine_coolant_temperatures', 'engine_thermostat_temperature', 'on_idle'], outputs=['cold_start_speeds_phases'] ) dsp.add_function( function=identify_cold_start_speeds_delta, inputs=['cold_start_speeds_phases', 'engine_speeds_out', 'engine_speeds_out_hot'], outputs=['cold_start_speeds_delta'] ) dsp.add_function( function=calibrate_cold_start_speed_model, inputs=['cold_start_speeds_phases', 'cold_start_speeds_delta', 'idle_engine_speed', 'on_engine', 'engine_coolant_temperatures', 'engine_speeds_out_hot'], outputs=['cold_start_speed_model'] ) dsp.add_function( function=calculate_cold_start_speeds_delta, inputs=['cold_start_speed_model', 'on_engine', 'engine_coolant_temperatures', 'engine_speeds_out_hot', 'idle_engine_speed'], outputs=['cold_start_speeds_delta'] ) return dsp
def cvt_model(): """ Defines the gear box model. .. dispatcher:: dsp >>> dsp = cvt_model() :return: The gear box model. :rtype: Dispatcher """ dsp = Dispatcher( name='CVT model', description='Models the gear box.' ) dsp.add_function( function=calibrate_cvt, inputs=['on_engine', 'engine_speeds_out', 'velocities', 'accelerations', 'gear_box_powers_out'], outputs=['CVT'] ) dsp.add_function( function=predict_gear_box_speeds_in__gears_and_max_gear, inputs=['CVT', 'velocities', 'accelerations', 'gear_box_powers_out'], outputs=['gear_box_speeds_in', 'gears', 'max_gear'], out_weight={'gear_box_speeds_in': 10} ) dsp.add_data( data_id='stop_velocity', default_value=dfl.values.stop_velocity ) dsp.add_function( function=identify_max_speed_velocity_ratio, inputs=['velocities', 'engine_speeds_out', 'idle_engine_speed', 'stop_velocity'], outputs=['max_speed_velocity_ratio'] ) return dsp
def _selector(name, data_in, data_out, setting): dsp = Dispatcher( name='%s selector' % name, description='Select the calibrated %s.' % name, ) errors, setting = [], setting or {} _sort_models = setting.pop('sort_models', sort_models) if 'weights' in setting: _weights = dsp_utl.map_list(setting['targets'], *setting.pop('weights')) else: _weights = None _get_best_model = partial(setting.pop('get_best_model', get_best_model), models_wo_err=setting.pop('models_wo_err', None), selector_id=dsp.name) dsp.add_data(data_id='error_settings', default_value={}) for i in data_in: e = 'error/%s' % i errors.append(e) dsp.add_function(function=_errors(name, i, data_out, setting), inputs=['error_settings', i] + [k for k in data_out if k != i], outputs=[e]) dsp.add_function(function_id='sort_models', function=partial(_sort_models, weights=_weights), inputs=errors, outputs=['rank']) dsp.add_function(function_id='get_best_model', function=_get_best_model, inputs=['rank'], outputs=['model', 'errors']) return dsp_utl.SubDispatch(dsp, outputs=['model', 'errors'], output_type='list')
def test_format_signature(self): setup_test() def formatsig(objtype, name, obj, args, retann): global directive inst = DispatcherDirective._registry[objtype](directive, name) inst.fullname = name inst.doc_as_attr = False # for class objtype inst.object = obj inst.objpath = [name] inst.args = args inst.retann = retann res = inst.format_signature() return res # no signatures for dispatchers dsp = Dispatcher() self.assertEqual(formatsig('dispatcher', 'dsp', dsp, None, None), '')
def _errors(name, data_id, data_out, setting): name = ''.join(k[0].upper() for k in name.split('_')) dsp = Dispatcher( name='%s-%s errors' % (name, data_id), description='Calculates the error of calibrated model.', ) setting = setting.copy() dsp.add_data(data_id='models', default_value=setting.pop('models', [])) select_data = partial(dsp_utl.selector, allow_miss=True) dsp.add_function(function_id='select_models', function=setting.pop('select_models', select_data), inputs=['models', data_id], outputs=['calibrated_models']) dsp.add_data(data_id='data_in', default_value=data_id) dsp.add_data(data_id='error_settings', default_value={}) for o in data_out: dsp.add_function(function=partial(dsp_utl.map_list, ['calibrated_models', 'data']), inputs=['calibrated_models', o], outputs=['input/%s' % o]) dsp.add_function(function=_error(name, data_id, o, setting), inputs=['input/%s' % o, 'error_settings'], outputs=['error/%s' % o]) i = ['error_settings', data_id] + [k for k in data_out if k != data_id] func = dsp_utl.SubDispatchFunction(dsp=dsp, function_id=dsp.name, inputs=i) return func
def calculate_wltp_velocities(): """ Defines the wltp cycle model. .. dispatcher:: dsp >>> dsp = calculate_wltp_velocities() :return: The wltp cycle model. :rtype: Dispatcher """ dsp = Dispatcher( name='WLTP velocities model', description='Returns the theoretical velocities of WLTP.' ) dsp.add_function( function=get_dfl, inputs=['base_model'], outputs=['driver_mass', 'resistance_coeffs_regression_curves', 'wltc_data'] ) dsp.add_function( function=calculate_unladen_mass, inputs=['vehicle_mass', 'driver_mass'], outputs=['unladen_mass'] ) dsp.add_function( function=calc_default_resistance_coeffs, inputs=['vehicle_mass', 'resistance_coeffs_regression_curves'], outputs=['road_loads'], weight=15 ) dsp.add_function( function=calculate_max_speed_velocity_ratio, inputs=['speed_velocity_ratios'], outputs=['max_speed_velocity_ratio'] ) dsp.add_function( function=calculate_max_velocity, inputs=['engine_max_speed_at_max_power', 'max_speed_velocity_ratio'], outputs=['max_velocity'] ) dsp.add_function( function=calculate_wltp_class, inputs=['wltc_data', 'engine_max_power', 'unladen_mass', 'max_velocity'], outputs=['wltp_class'] ) dsp.add_function( function=get_class_data, inputs=['wltc_data', 'wltp_class'], outputs=['class_data'] ) dsp.add_function( function=get_class_velocities, inputs=['class_data', 'times'], outputs=['class_velocities'], weight=25 ) from ..vehicle import vehicle func = dsp_utl.SubDispatchFunction( dsp=vehicle(), function_id='calculate_class_powers', inputs=['vehicle_mass', 'velocities', 'climbing_force', 'road_loads', 'inertial_factor', 'times'], outputs=['motive_powers'] ) dsp.add_function( function=func, inputs=['vehicle_mass', 'class_velocities', 'climbing_force', 'road_loads', 'inertial_factor', 'times'], outputs=['class_powers'] ) dsp.add_data( data_id='downscale_factor_threshold', default_value=dfl.values.downscale_factor_threshold ) dsp.add_function( function=calculate_downscale_factor, inputs=['class_data', 'downscale_factor_threshold', 'max_velocity', 'engine_max_power', 'class_powers', 'times'], outputs=['downscale_factor'] ) dsp.add_function( function=get_downscale_phases, inputs=['class_data'], outputs=['downscale_phases'] ) dsp.add_function( function=wltp_velocities, inputs=['downscale_factor', 'class_velocities', 'downscale_phases', 'times'], outputs=['velocities'] ) return dsp
def wltp_cycle(): """ Defines the wltp cycle model. .. dispatcher:: dsp >>> dsp = wltp_cycle() :return: The wltp cycle model. :rtype: Dispatcher """ dsp = Dispatcher( name='WLTP cycle model', description='Returns the theoretical times, velocities, and gears of ' 'WLTP.' ) dsp.add_data( data_id='initial_temperature', default_value=dfl.values.initial_temperature_WLTP ) dsp.add_data( data_id='wltp_base_model', default_value=deepcopy(dfl.values.wltp_base_model) ) dsp.add_function( function=define_wltp_base_model, inputs=['wltp_base_model'], outputs=['base_model'] ) dsp.add_data( data_id='time_sample_frequency', default_value=dfl.values.time_sample_frequency ) dsp.add_function( function=wltp_time_length, inputs=['time_sample_frequency'], outputs=['time_length'], weight=5 ) dsp.add_dispatcher( dsp=calculate_wltp_velocities(), inputs={ 'times': 'times', 'base_model': 'base_model', 'velocities': 'velocities', 'speed_velocity_ratios': 'speed_velocity_ratios', 'inertial_factor': 'inertial_factor', 'downscale_phases': 'downscale_phases', 'climbing_force': 'climbing_force', 'downscale_factor': 'downscale_factor', 'downscale_factor_threshold': 'downscale_factor_threshold', 'vehicle_mass': 'vehicle_mass', 'driver_mass': 'driver_mass', 'road_loads': 'road_loads', 'engine_max_power': 'engine_max_power', 'engine_max_speed_at_max_power': 'engine_max_speed_at_max_power', 'max_velocity': 'max_velocity', 'wltp_class': 'wltp_class', 'max_speed_velocity_ratio': 'max_speed_velocity_ratio' }, outputs={ 'velocities': 'velocities' } ) dsp.add_function( function=dsp_utl.add_args(wltp_gears), inputs=['gear_box_type', 'full_load_curve', 'velocities', 'accelerations', 'motive_powers', 'speed_velocity_ratios', 'idle_engine_speed', 'engine_max_speed_at_max_power', 'engine_max_power', 'base_model'], outputs=['gears'], input_domain=lambda *args: args[0] == 'manual' ) return dsp
def mechanical(): """ Defines the mechanical gear box model. .. dispatcher:: dsp >>> dsp = mechanical() :return: The gear box model. :rtype: Dispatcher """ dsp = Dispatcher(name='mechanical model', description='Models the gear box.') dsp.add_data(data_id='stop_velocity', default_value=dfl.values.stop_velocity) dsp.add_data(data_id='plateau_acceleration', default_value=dfl.values.plateau_acceleration) dsp.add_data(data_id='change_gear_window_width', default_value=dfl.values.change_gear_window_width) dsp.add_function(function=identify_gears, inputs=[ 'times', 'velocities', 'accelerations', 'engine_speeds_out', 'velocity_speed_ratios', 'stop_velocity', 'plateau_acceleration', 'change_gear_window_width', 'idle_engine_speed' ], outputs=['gears']) dsp.add_function(function=calculate_gear_box_speeds_in, inputs=[ 'gears', 'velocities', 'velocity_speed_ratios', 'stop_velocity' ], outputs=['gear_box_speeds_in'], weight=25) dsp.add_function( function=calculate_gear_box_speeds_in_v1, inputs=['gears', 'gear_box_speeds_out', 'gear_box_ratios'], outputs=['gear_box_speeds_in']) dsp.add_function( function=calculate_speed_velocity_ratios, inputs=['gear_box_ratios', 'final_drive_ratio', 'r_dynamic'], outputs=['speed_velocity_ratios']) dsp.add_function( function=identify_speed_velocity_ratios, inputs=['gears', 'velocities', 'gear_box_speeds_in', 'stop_velocity'], outputs=['speed_velocity_ratios'], weight=5) dsp.add_function( function=identify_speed_velocity_ratios, inputs=['gears', 'velocities', 'engine_speeds_out', 'stop_velocity'], outputs=['speed_velocity_ratios'], weight=10) dsp.add_function(function=calculate_velocity_speed_ratios, inputs=['speed_velocity_ratios'], outputs=['velocity_speed_ratios']) dsp.add_function(function=identify_velocity_speed_ratios, inputs=[ 'engine_speeds_out', 'velocities', 'idle_engine_speed', 'stop_velocity' ], outputs=['velocity_speed_ratios'], weight=50) dsp.add_function( function=calculate_gear_box_ratios, inputs=['velocity_speed_ratios', 'final_drive_ratio', 'r_dynamic'], outputs=['gear_box_ratios']) dsp.add_function(function=identify_max_gear, inputs=['speed_velocity_ratios'], outputs=['max_gear']) return dsp
def wheels(): """ Defines the wheels model. .. dispatcher:: dsp >>> dsp = wheels() :return: The wheels model. :rtype: Dispatcher """ dsp = Dispatcher(name='Wheel model', description='It models the wheel dynamics.') dsp.add_function(function=calculate_wheel_torques, inputs=['wheel_powers', 'wheel_speeds'], outputs=['wheel_torques']) dsp.add_function(function=calculate_wheel_powers, inputs=['wheel_torques', 'wheel_speeds'], outputs=['wheel_powers']) dsp.add_function(function=calculate_wheel_speeds, inputs=['velocities', 'r_dynamic'], outputs=['wheel_speeds']) dsp.add_function(function=identify_r_dynamic, inputs=[ 'velocity_speed_ratios', 'gear_box_ratios', 'final_drive_ratio' ], outputs=['r_dynamic']) dsp.add_function(function=identify_r_dynamic_v1, inputs=[ 'velocities', 'gears', 'engine_speeds_out', 'gear_box_ratios', 'final_drive_ratio', 'stop_velocity' ], outputs=['r_dynamic'], weight=10) dsp.add_data(data_id='stop_velocity', default_value=dfl.values.stop_velocity) dsp.add_data(data_id='plateau_acceleration', default_value=dfl.values.plateau_acceleration) dsp.add_data(data_id='change_gear_window_width', default_value=dfl.values.change_gear_window_width) dsp.add_function(function=calculate_tyre_dimensions, inputs=['tyre_code'], outputs=['tyre_dimensions']) dsp.add_function(function=calculate_r_wheels, inputs=['tyre_dimensions'], outputs=['r_wheels']) dsp.add_function(function=define_tyre_code, inputs=['tyre_dimensions'], outputs=['tyre_code']) dsp.add_function(function=default_tyre_code, inputs=['r_dynamic'], outputs=['tyre_code'], weight=5) dsp.add_data(data_id='tyre_dynamic_rolling_coefficient', default_value=dfl.values.tyre_dynamic_rolling_coefficient, initial_dist=50) dsp.add_function(function=calculate_r_dynamic, inputs=['r_wheels', 'tyre_dynamic_rolling_coefficient'], outputs=['r_dynamic']) dsp.add_function(function=identify_tyre_dynamic_rolling_coefficient, inputs=['r_wheels', 'r_dynamic'], outputs=['tyre_dynamic_rolling_coefficient']) dsp.add_function(function=identify_r_dynamic_v2, inputs=[ 'times', 'velocities', 'accelerations', 'r_wheels', 'engine_speeds_out', 'gear_box_ratios', 'final_drive_ratio', 'idle_engine_speed', 'stop_velocity', 'plateau_acceleration', 'change_gear_window_width' ], outputs=['r_dynamic'], weight=11) dsp.add_function(function=dsp_utl.bypass, inputs=['motive_powers'], outputs=['wheel_powers']) return dsp
def torque_converter(): """ Defines the torque converter model. .. dispatcher:: dsp >>> dsp = torque_converter() :return: The torque converter model. :rtype: Dispatcher """ dsp = Dispatcher( name='Torque_converter', description='Models the torque converter.' ) dsp.add_data( data_id='calibration_tc_speed_threshold', default_value=dfl.values.calibration_tc_speed_threshold ) dsp.add_data( data_id='stop_velocity', default_value=dfl.values.stop_velocity ) dsp.add_data( data_id='lock_up_tc_limits', default_value=dfl.values.lock_up_tc_limits ) dsp.add_function( function=identify_torque_converter_speeds_delta, inputs=['engine_speeds_out', 'engine_speeds_out_hot', 'cold_start_speeds_delta'], outputs=['torque_converter_speeds_delta'] ) dsp.add_function( function=calibrate_torque_converter_model, inputs=['lock_up_tc_limits', 'calibration_tc_speed_threshold', 'stop_velocity', 'torque_converter_speeds_delta', 'accelerations', 'velocities', 'gear_box_speeds_in', 'gears'], outputs=['torque_converter_model'] ) dsp.add_function( function=predict_torque_converter_speeds_delta, inputs=['lock_up_tc_limits', 'torque_converter_model', 'accelerations', 'velocities', 'gear_box_speeds_in', 'gears'], outputs=['torque_converter_speeds_delta'] ) dsp.add_function( function=define_k_factor_curve, inputs=['stand_still_torque_ratio', 'lockup_speed_ratio'], outputs=['k_factor_curve'] ) dsp.add_function( function=default_tc_k_factor_curve, outputs=['k_factor_curve'], weight=2 ) return dsp
def engine(): """ Defines the engine model. .. dispatcher:: dsp >>> dsp = engine() :return: The engine model. :rtype: Dispatcher """ dsp = Dispatcher(name='Engine', description='Models the vehicle engine.') dsp.add_function(function=default_ignition_type, inputs=['engine_type'], outputs=['ignition_type']) dsp.add_function(function=default_ignition_type_v1, inputs=['fuel_type'], outputs=['ignition_type'], weight=1) dsp.add_function(function=get_full_load, inputs=['ignition_type'], outputs=['full_load_curve'], weight=20) dsp.add_data(data_id='is_cycle_hot', default_value=dfl.values.is_cycle_hot) dsp.add_function(function=select_initial_friction_params, inputs=['co2_params_initial_guess'], outputs=['initial_friction_params']) from ..wheels import calculate_wheel_powers, calculate_wheel_torques dsp.add_function(function_id='calculate_full_load_powers', function=calculate_wheel_powers, inputs=['full_load_torques', 'full_load_speeds'], outputs=['full_load_powers']) dsp.add_function(function_id='calculate_full_load_speeds', function=calculate_wheel_torques, inputs=['full_load_powers', 'full_load_torques'], outputs=['full_load_speeds']) dsp.add_function(function=calculate_full_load_speeds_and_powers, inputs=[ 'full_load_curve', 'engine_max_power', 'engine_max_speed_at_max_power', 'idle_engine_speed' ], outputs=['full_load_speeds', 'full_load_powers']) dsp.add_function( function=calculate_full_load, inputs=['full_load_speeds', 'full_load_powers', 'idle_engine_speed'], outputs=[ 'full_load_curve', 'engine_max_power', 'engine_max_speed_at_max_power' ]) # Idle engine speed dsp.add_data(data_id='idle_engine_speed_median', description='Idle engine speed [RPM].') # default value dsp.add_data(data_id='idle_engine_speed_std', default_value=dfl.values.idle_engine_speed_std, description='Standard deviation of idle engine speed [RPM].') # identify idle engine speed dsp.add_function( function=identify_idle_engine_speed_out, inputs=[ 'velocities', 'engine_speeds_out', 'stop_velocity', 'min_engine_on_speed' ], outputs=['idle_engine_speed_median', 'idle_engine_speed_std']) # set idle engine speed tuple dsp.add_function( function=dsp_utl.bypass, inputs=['idle_engine_speed_median', 'idle_engine_speed_std'], outputs=['idle_engine_speed']) # set idle engine speed tuple dsp.add_function( function=dsp_utl.bypass, inputs=['idle_engine_speed'], outputs=['idle_engine_speed_median', 'idle_engine_speed_std']) from .thermal import thermal dsp.add_dispatcher(include_defaults=True, dsp=thermal(), dsp_id='thermal', inputs={ 'times': 'times', 'on_engine': 'on_engine', 'accelerations': 'accelerations', 'engine_coolant_temperatures': 'engine_coolant_temperatures', 'final_drive_powers_in': 'final_drive_powers_in', 'idle_engine_speed': 'idle_engine_speed', 'engine_speeds_out_hot': 'engine_speeds_out_hot', 'engine_temperature_regression_model': 'engine_temperature_regression_model', 'initial_engine_temperature': 'initial_engine_temperature', 'engine_thermostat_temperature': 'engine_thermostat_temperature', 'engine_thermostat_temperature_window': 'engine_thermostat_temperature_window', 'max_engine_coolant_temperature': 'max_engine_coolant_temperature' }, outputs={ 'engine_temperature_regression_model': 'engine_temperature_regression_model', 'engine_thermostat_temperature': 'engine_thermostat_temperature', 'engine_thermostat_temperature_window': 'engine_thermostat_temperature_window', 'initial_engine_temperature': 'initial_engine_temperature', 'max_engine_coolant_temperature': 'max_engine_coolant_temperature', 'engine_temperature_derivatives': 'engine_temperature_derivatives' }) dsp.add_function(function=calculate_engine_max_torque, inputs=[ 'engine_max_power', 'engine_max_speed_at_max_power', 'ignition_type' ], outputs=['engine_max_torque']) dsp.add_function(function=calculate_engine_max_torque, inputs=[ 'engine_max_torque', 'engine_max_speed_at_max_power', 'ignition_type' ], outputs=['engine_max_power']) from .start_stop import start_stop dsp.add_dispatcher(include_defaults=True, dsp=start_stop(), dsp_id='start_stop', inputs={ 'is_hybrid': 'is_hybrid', 'use_basic_start_stop': 'use_basic_start_stop', 'start_stop_model': 'start_stop_model', 'times': 'times', 'velocities': 'velocities', 'accelerations': 'accelerations', 'engine_coolant_temperatures': 'engine_coolant_temperatures', 'state_of_charges': 'state_of_charges', 'gears': 'gears', 'correct_start_stop_with_gears': 'correct_start_stop_with_gears', 'start_stop_activation_time': 'start_stop_activation_time', 'min_time_engine_on_after_start': 'min_time_engine_on_after_start', 'has_start_stop': 'has_start_stop', 'gear_box_type': 'gear_box_type', 'on_engine': 'on_engine', 'engine_speeds_out': 'engine_speeds_out', 'idle_engine_speed': 'idle_engine_speed', 'engine_starts': 'engine_starts' }, outputs={ 'on_engine': 'on_engine', 'engine_starts': 'engine_starts', 'use_basic_start_stop': 'use_basic_start_stop', 'start_stop_model': 'start_stop_model', 'correct_start_stop_with_gears': 'correct_start_stop_with_gears' }) dsp.add_data(data_id='plateau_acceleration', default_value=dfl.values.plateau_acceleration) dsp.add_function( function=calculate_engine_speeds_out_hot, inputs=['gear_box_speeds_in', 'on_engine', 'idle_engine_speed'], outputs=['engine_speeds_out_hot']) dsp.add_function(function=identify_on_idle, inputs=[ 'velocities', 'engine_speeds_out_hot', 'gears', 'stop_velocity', 'min_engine_on_speed' ], outputs=['on_idle']) from .cold_start import cold_start dsp.add_dispatcher(dsp=cold_start(), inputs={ 'engine_speeds_out': 'engine_speeds_out', 'engine_speeds_out_hot': 'engine_speeds_out_hot', 'engine_coolant_temperatures': 'engine_coolant_temperatures', 'engine_thermostat_temperature': 'engine_thermostat_temperature', 'on_idle': 'on_idle', 'cold_start_speeds_phases': 'cold_start_speeds_phases', 'idle_engine_speed': 'idle_engine_speed', 'on_engine': 'on_engine', 'cold_start_speed_model': 'cold_start_speed_model' }, outputs={ 'cold_start_speeds_phases': 'cold_start_speeds_phases', 'cold_start_speeds_delta': 'cold_start_speeds_delta', 'cold_start_speed_model': 'cold_start_speed_model' }) dsp.add_function(function=calculate_engine_speeds_out, inputs=[ 'on_engine', 'idle_engine_speed', 'engine_speeds_out_hot', 'cold_start_speeds_delta', 'clutch_tc_speeds_delta' ], outputs=['engine_speeds_out']) dsp.add_function(function=calculate_uncorrected_engine_powers_out, inputs=[ 'times', 'engine_moment_inertia', 'clutch_tc_powers', 'engine_speeds_out', 'on_engine', 'auxiliaries_power_losses', 'gear_box_type', 'on_idle', 'alternator_powers_demand' ], outputs=['uncorrected_engine_powers_out']) dsp.add_function(function=calculate_min_available_engine_powers_out, inputs=[ 'engine_stroke', 'engine_capacity', 'initial_friction_params', 'engine_speeds_out' ], outputs=['min_available_engine_powers_out']) dsp.add_function(function=calculate_max_available_engine_powers_out, inputs=[ 'engine_max_speed_at_max_power', 'idle_engine_speed', 'engine_max_power', 'full_load_curve', 'engine_speeds_out' ], outputs=['max_available_engine_powers_out']) dsp.add_function( function=correct_engine_powers_out, inputs=[ 'max_available_engine_powers_out', 'min_available_engine_powers_out', 'uncorrected_engine_powers_out' ], outputs=['engine_powers_out', 'missing_powers', 'brake_powers']) dsp.add_function(function=check_vehicle_has_sufficient_power, inputs=['missing_powers'], outputs=['has_sufficient_power']) dsp.add_function(function=calculate_mean_piston_speeds, inputs=['engine_speeds_out', 'engine_stroke'], outputs=['mean_piston_speeds']) dsp.add_data(data_id='engine_is_turbo', default_value=dfl.values.engine_is_turbo) dsp.add_function(function=calculate_engine_type, inputs=['ignition_type', 'engine_is_turbo'], outputs=['engine_type']) dsp.add_function(function=calculate_engine_moment_inertia, inputs=['engine_capacity', 'ignition_type'], outputs=['engine_moment_inertia']) dsp.add_data(data_id='auxiliaries_torque_loss', default_value=dfl.values.auxiliaries_torque_loss) dsp.add_data(data_id='auxiliaries_power_loss', default_value=dfl.values.auxiliaries_power_loss) dsp.add_function(function=calculate_auxiliaries_torque_losses, inputs=['times', 'auxiliaries_torque_loss'], outputs=['auxiliaries_torque_losses']) dsp.add_function(function=calculate_auxiliaries_power_losses, inputs=[ 'auxiliaries_torque_losses', 'engine_speeds_out', 'on_engine', 'auxiliaries_power_loss' ], outputs=['auxiliaries_power_losses']) from .co2_emission import co2_emission dsp.add_dispatcher(include_defaults=True, dsp=co2_emission(), dsp_id='CO2_emission_model', inputs={ 'co2_emission_low': 'co2_emission_low', 'co2_emission_medium': 'co2_emission_medium', 'co2_emission_high': 'co2_emission_high', 'co2_emission_extra_high': 'co2_emission_extra_high', 'co2_emission_UDC': 'co2_emission_UDC', 'co2_emission_EUDC': 'co2_emission_EUDC', 'co2_params': 'co2_params', 'co2_params_calibrated': ('co2_params_calibrated', 'co2_params'), 'cycle_type': 'cycle_type', 'is_cycle_hot': 'is_cycle_hot', 'engine_capacity': 'engine_capacity', 'engine_fuel_lower_heating_value': 'engine_fuel_lower_heating_value', 'engine_idle_fuel_consumption': 'engine_idle_fuel_consumption', 'engine_powers_out': 'engine_powers_out', 'engine_speeds_out': 'engine_speeds_out', 'engine_stroke': 'engine_stroke', 'engine_coolant_temperatures': 'engine_coolant_temperatures', 'engine_thermostat_temperature': 'engine_thermostat_temperature', 'engine_type': 'engine_type', 'fuel_carbon_content_percentage': 'fuel_carbon_content_percentage', 'fuel_carbon_content': 'fuel_carbon_content', 'idle_engine_speed': 'idle_engine_speed', 'mean_piston_speeds': 'mean_piston_speeds', 'on_engine': 'on_engine', 'engine_thermostat_temperature_window': 'engine_thermostat_temperature_window', 'times': 'times', 'velocities': 'velocities', 'calibration_status': 'calibration_status', 'initial_engine_temperature': 'initial_engine_temperature', 'fuel_consumptions': 'fuel_consumptions', 'co2_emissions': 'co2_emissions', 'co2_normalization_references': 'co2_normalization_references', 'fuel_type': 'fuel_type', 'phases_integration_times': 'phases_integration_times', 'enable_willans': 'enable_willans', 'enable_phases_willans': 'enable_phases_willans', 'accelerations': 'accelerations', 'motive_powers': 'motive_powers', 'missing_powers': 'missing_powers', 'stop_velocity': 'stop_velocity', 'min_engine_on_speed': 'min_engine_on_speed', 'fuel_density': 'fuel_density', }, outputs={ 'co2_emissions_model': 'co2_emissions_model', 'co2_emission_value': 'co2_emission_value', 'co2_emissions': 'co2_emissions', 'identified_co2_emissions': 'identified_co2_emissions', 'co2_error_function_on_emissions': 'co2_error_function_on_emissions', 'co2_error_function_on_phases': 'co2_error_function_on_phases', 'co2_params_calibrated': 'co2_params_calibrated', 'co2_params_initial_guess': 'co2_params_initial_guess', 'fuel_consumptions': 'fuel_consumptions', 'phases_co2_emissions': 'phases_co2_emissions', 'calibration_status': 'calibration_status', 'willans_factors': 'willans_factors', 'optimal_efficiency': 'optimal_efficiency', 'phases_fuel_consumptions': 'phases_fuel_consumptions', 'extended_phases_integration_times': 'extended_phases_integration_times', 'extended_phases_co2_emissions': 'extended_phases_co2_emissions', 'after_treatment_temperature_threshold': 'after_treatment_temperature_threshold', 'phases_willans_factors': 'phases_willans_factors', 'fuel_carbon_content_percentage': 'fuel_carbon_content_percentage', 'fuel_carbon_content': 'fuel_carbon_content', 'engine_fuel_lower_heating_value': 'engine_fuel_lower_heating_value', }, inp_weight={'co2_params': EPS}) return dsp
def load_inputs(): """ Defines a module to load the input file of the CO2MPAS model. .. dispatcher:: dsp >>> dsp = load_inputs() :return: The load input module. :rtype: SubDispatchFunction """ dsp = Dispatcher( name='load_inputs', description='Loads from files the inputs for the CO2MPAS model.' ) dsp.add_function( function=get_cache_fpath, inputs=['input_file_name'], outputs=['cache_file_name'] ) dsp.add_data( data_id='overwrite_cache', default_value=False, ) dsp.add_function( function_id='load_data_from_cache', function=dsp_utl.add_args(load_from_dill, n=2), inputs=['overwrite_cache', 'input_file_name', 'cache_file_name'], outputs=['data'], input_domain=check_cache_fpath_exists ) dsp.add_function( function=parse_excel_file, inputs=['input_file_name'], outputs=['data'], input_domain=partial(check_file_format, extensions=('.xlsx', '.xls')), weight=5 ) dsp.add_function( function=load_from_dill, inputs=['input_file_name'], outputs=['data'], input_domain=partial(check_file_format, extensions=('.dill',)), weight=5 ) dsp.add_function( function_id='load_from_xlasso', function=lasso, inputs=['input_file_name'], outputs=['data'], input_domain=check_xlasso, weight=5 ) dsp.add_function( function_id='cache_parsed_data', function=save_dill, inputs=['data', 'cache_file_name'] ) dsp.add_function( function=partial(validate_data, read_schema=define_data_schema()), inputs=['data', 'soft_validation'], outputs=['validated_data', 'validated_plan'], weight=1 ) dsp.add_data( data_id='validated_data', function=check_data_version ) return dsp
def start_stop(): """ Defines the engine start/stop model. .. dispatcher:: dsp >>> dsp = start_stop() :return: The engine start/stop model. :rtype: Dispatcher """ dsp = Dispatcher(name='start_stop', description='Models the engine start/stop strategy.') dsp.add_function(function=identify_on_engine, inputs=[ 'times', 'engine_speeds_out', 'idle_engine_speed', 'min_time_engine_on_after_start' ], outputs=['on_engine']) dsp.add_function(function=identify_engine_starts, inputs=['on_engine'], outputs=['engine_starts']) dsp.add_data(data_id='start_stop_activation_time', default_value=dfl.values.start_stop_activation_time) dsp.add_function(function=calibrate_start_stop_model, inputs=[ 'on_engine', 'velocities', 'accelerations', 'engine_coolant_temperatures', 'state_of_charges' ], outputs=['start_stop_model']) dsp.add_function(function=default_correct_start_stop_with_gears, inputs=['gear_box_type'], outputs=['correct_start_stop_with_gears']) dsp.add_data(data_id='min_time_engine_on_after_start', default_value=dfl.values.min_time_engine_on_after_start) dsp.add_data(data_id='has_start_stop', default_value=dfl.values.has_start_stop) dsp.add_data(data_id='is_hybrid', default_value=dfl.values.is_hybrid) dsp.add_function(function=default_use_basic_start_stop_model, inputs=['is_hybrid'], outputs=['use_basic_start_stop']) dsp.add_function( function=predict_engine_start_stop, inputs=[ 'start_stop_model', 'times', 'velocities', 'accelerations', 'engine_coolant_temperatures', 'state_of_charges', 'gears', 'correct_start_stop_with_gears', 'start_stop_activation_time', 'min_time_engine_on_after_start', 'has_start_stop', 'use_basic_start_stop' ], outputs=['on_engine', 'engine_starts']) return dsp
def cycle(): """ Defines the cycle model. .. dispatcher:: dsp >>> dsp = cycle() :return: The cycle model. :rtype: Dispatcher """ dsp = Dispatcher( name='Cycle model', description='Returns the theoretical times, velocities, and gears.') from .NEDC import nedc_cycle dsp.add_dispatcher(include_defaults=True, dsp=nedc_cycle(), inputs={ 'cycle_type': dsp_utl.SINK, 'k1': 'k1', 'k2': 'k2', 'k5': 'k5', 'max_gear': 'max_gear', 'gear_box_type': 'gear_box_type', 'times': 'times', 'time_sample_frequency': 'time_sample_frequency', 'gears': 'gears' }, outputs={ 'velocities': 'velocities', 'gears': 'gears', 'time_length': 'time_length', 'initial_temperature': 'initial_temperature' }, input_domain=is_nedc) from .WLTP import wltp_cycle dsp.add_dispatcher(include_defaults=True, dsp=wltp_cycle(), inputs={ 'cycle_type': dsp_utl.SINK, 'gear_box_type': 'gear_box_type', 'times': 'times', 'wltp_base_model': 'wltp_base_model', 'velocities': 'velocities', 'accelerations': 'accelerations', 'motive_powers': 'motive_powers', 'speed_velocity_ratios': 'speed_velocity_ratios', 'idle_engine_speed': 'idle_engine_speed', 'inertial_factor': 'inertial_factor', 'downscale_phases': 'downscale_phases', 'climbing_force': 'climbing_force', 'full_load_curve': 'full_load_curve', 'downscale_factor': 'downscale_factor', 'downscale_factor_threshold': 'downscale_factor_threshold', 'vehicle_mass': 'vehicle_mass', 'driver_mass': 'driver_mass', 'road_loads': 'road_loads', 'engine_max_power': 'engine_max_power', 'engine_max_speed_at_max_power': 'engine_max_speed_at_max_power', 'max_velocity': 'max_velocity', 'wltp_class': 'wltp_class', 'max_speed_velocity_ratio': 'max_speed_velocity_ratio', 'time_sample_frequency': 'time_sample_frequency', 'gears': 'gears' }, outputs={ 'velocities': 'velocities', 'gears': 'gears', 'time_length': 'time_length', 'initial_temperature': 'initial_temperature' }, input_domain=is_wltp) dsp.add_function(function=cycle_times, inputs=['time_sample_frequency', 'time_length'], outputs=['times']) dsp.add_function(function=len, inputs=['velocities'], outputs=['time_length']) dsp.add_function(function=len, inputs=['gears'], outputs=['time_length'], weight=1) return dsp
def test_load_default_values(self): save_default_values(self.dsp, self.tmp) dsp = Dispatcher(dmap=self.dsp.dmap) load_default_values(dsp, self.tmp) self.assertEqual(dsp.default_values, self.dsp.default_values) self.assertEqual(dsp.dispatch()['b'], 6)