[docs]defcombineiod(input_dict,output_dict):"""combines the input and output dictionaries into a single dictionary Args: i (dict): dictionary of the input names and values o (dict): dictionary of the output names and values Returns: dict: dictionary of the input and output names and values """return{**input_dict,**output_dict}
[docs]defiskeyinput(key:str):"""returns True if the key is an input to the control system and False if it is an output Args: key (str): string of the input or output name Returns: boolean: is the name an input or output name. true if input, false if output, none if not a valid name """splitlist=key.split('.')if'in'insplitlistand'out'notinsplitlist:# if 'in' is in the keyreturnTrue# then it is an input so return Trueelif'out'insplitlistand'in'notinsplitlist:# if 'out' is in the keyreturnFalse# then it is an output so return Falseelse:# if neither 'in' or 'out' is in the key then it is not an input or outputprint('cannot identify if key is input or output. KEY:'+key)returnifsplitlist[1]=='in':# if 'in' is in the keyreturnTrue# then it is an input so return Trueelifsplitlist[1]=='out':# if 'out' is in the keyreturnFalse# then it is an output so return Falseelse:# if neither 'in' or 'out' is in the key then it is not an input or outputprint('cannot identify if key is input or output. KEY:'+key)return
[docs]deflistinputs(iod,values=False):"""returns a list of the inputs to the control system either their names or their values Args: iod (dict): dictionary of the input and output names and indices or wield.control.mimo iod object values (bool, optional): if True, return the values of the inputs. Defaults to False. Returns: list: list of the input names or values if values is True """iftype(iod)isnotdict:try:iod=iod.iodexcept:iod=dict(iod)ifvalues:return[iod[key]forkeyiniod.keys()ifiskeyinput(key)]else:return[keyforkeyiniod.keys()ifiskeyinput(key)]# return list of input names
[docs]deflistoutputs(iod,values=False):"""returns a list of the outputs to the control system either their names or their values Args: iod (dict): dictionary of the input and output names and indices or wield.control.mimo iod object values (bool, optional): if True, return the values of the outputs. Defaults to False. Returns: list: list of the output names or values if values is True """iftype(iod)isnotdict:try:iod=iod.iodexcept:iod=dict(iod)ifvalues:return[iod[key]forkeyiniod.keys()ifnotiskeyinput(key)]else:return[keyforkeyiniod.keys()ifnotiskeyinput(key)]# return list of output names
[docs]defconnectDicts(d1,d2,inlist=None,outlist=None):"""Combine input and output dictionaries Args: d1 (dict): first dictionary d2 (dict): second dictionary inlist (list, optional): list of inputs to connect. Defaults to None. outlist (list, optional): list of outputs to connect. Defaults to None. Returns: dict: combined dictionary """connectedDict=d1.copy()d1_num_ins=len(listinputs(d1))d1_num_outs=len(listoutputs(d1))d2_tmp=d2.copy()forkeyind2.keys():ifiskeyinput(key):d2_tmp[key]+=d1_num_inselse:d2_tmp[key]+=d1_num_outsconnectedDict.update(d2_tmp)forkeyinconnectedDict.keys():ifiskeyinput(key)andinlistisnotNoneandconnectedDict[key]notininlist:delconnectedDict['key']ifnotiskeyinput(key)andoutlistisnotNoneandconnectedDict[key]notinoutlist:delconnectedDict['key']connectedDict=squareDict(connectedDict)returnconnectedDict
[docs]defsquareDict(d):"""Square the dictionary by removing any holes in the indices and moving down those with higher indices to fill the holes Args: d (dict): dictionary to square Returns: dict: squared dictionary """inputs=[]outputs=[]d=d.copy()forkeyind.keys():ifiskeyinput(key):inputs.append(d[key])else:outputs.append(d[key])inputs.sort()outputs.sort()#missing_inputs = [ele for ele in range(max(inputs)+1) if ele not in inputs]#missing_outputs = [ele for ele in range(max(outputs)+1) if ele not in outputs]forkeyind.keys():ifiskeyinput(key):d[key]=inputs.index(d[key])else:d[key]=outputs.index(d[key])returnd
[docs]defchangedictnamespace(dict,namespace,append=False):"""Change the namespace of a dictionary. Args: dict (dict): The dictionary to change the namespace of. namespace (str): The new namespace. append (bool): wheather to just append the new name space to the old one 'A.in' becomes 'EA.in' Returns: dict: The dictionary with the new namespace. """newdict={}forkey,valueindict.items():ifappend:newdict[namespace+'.'.join(key.split('.'))]=valueelse:newdict[namespace+'.'+'.'.join(key.split('.')[1:])]=valuereturnnewdict
[docs]defremoveIodIndices(iod,inputs_to_remove,outputs_to_remove):"""Take an iod and remove the inputs and outputs specified by the indices and or names provided in the `inputs_to_remove` and `outputs_to_remove` lists Args: iod (dict or Bunch): input/output dictionary or bunch system with iod as attribute inputs_to_remove (list): List of indices or names of inputs to remove outputs_to_remove (list): List of indices or names of outputs to remove Returns: dict: Input/output dictionary with the removed inputs and outputs """# Set the iod so that this function can be passed a Bunch or a dicttry:iod=iod.iodexcept:passnewiod={}# Create a new iodinputs_removed=0# Keep track of how many inputs have been removedoutputs_removed=0# Keep track of how many outputs have been removedforiiniod.keys():# Loop over all keysifiskeyinput(i):# If the key is an inputifiod[i]notininputs_to_remove:#and i not in inputs_to_remove: # If the input is not to be removednewiod[i]=iod[i]# Add the input to the new iodelse:inputs_removed+=1# Increment the number of inputs removedelse:# If the key is an outputifiod[i]notinoutputs_to_remove:#and i not in outputs_to_remove: # If the output is not to be removednewiod[i]=iod[i]# Add the output to the new iodelse:outputs_removed+=1# Increment the number of outputs removed# Warn the user if any inputs or outputs were removedifinputs_removed!=len(inputs_to_remove):warnings.warn(f'problem removing inputs: {inputs_removed} inputs removed, {len(inputs_to_remove)} inputs to remove. This error is likely caused by an input being listed that does not exist in the iod.')ifoutputs_removed!=len(outputs_to_remove):warnings.warn(f'problem removing outputs: {outputs_removed} outputs removed, {len(outputs_to_remove)} outputs to remove. This error is likely caused by an output being listed that does not exist in the iod.')newiod=squareDict(newiod)# Square the new iodreturnnewiod
[docs]defgetNamespace(sys):"""Get the namespace of a system Args: sys (dict or Bunch): State space model or bunch system with mod as attribute Returns: dict: Namespace """try:iod=sys.iodexcept:iod=sysnamespace=[]foriiniod.keys():namespace.append(i[0])if([namespace[0]]*len(namespace)==namespace):namespace=namespace[0]else:warnings.warn('Not all keys have the same namespace')print('all namespaces: {}'.format(namespace))namespace=Nonereturnnamespace