Exemplo n.º 1
0
def convertFromFmi(fmuFilename, fmi=None):
    ''' Returns data to initialize an MTSF result file from an FMU.
        The call to initialize an MTSF result file is
            pyMtsf.MTSF(resultFileName, modelDescription, modelVariables, experimentSetup, simpleTypes, units, enumerationsMatrix)
        The missing data is resultFileName and experimentSetup to be specified before initializing the MTSF object.

        Inputs                       Type:
            fmuFilename              String
            fmi                      FMIDescription      [optional]
            if fmi is given, then fmuFilename is ignored. Otherwise the FMI description is loaded from the given file.

        Outputs
           modelDescription          pyMtsf.ModelDescription
           modelVariables            pyMtsf.ModelVariables
           simpleTypes               list of pyMtsf.SimpleType
           units                     list of pyMtsf.Unit
           enumerationsMatrix        list of pyMtsf.Enumeration
    '''

    def _None2Str(x):
        if x is None:
            return ''
        else:
            return x


    # Load FMIDescription if necessary
    if fmi is None:
        fmuFile = zipfile.ZipFile(os.getcwd() + u'\\' + fmuFilename + u'.fmu', 'r')
        fmi = FMIDescription(fmuFile.open('modelDescription.xml'))

    # Prepare some variables
    allSeriesNames = [x.name for x in StandardSeriesForFmi]
    variable = collections.OrderedDict()
    simpleTypes = []
    units = []
    enumerationsMatrix = []
    variable['Time'] = pyMtsf.ScalarModelVariable('Continuous Time', 'input', 0, 'continuous', allSeriesNames.index('Continuous'), pyMtsf.StandardCategoryNames.index(pyMtsf.CategoryMapping['Real']), None, 0)
    variable['TimeDiscrete'] = pyMtsf.ScalarModelVariable('Discrete Time at events', 'input', 0, 'discrete', allSeriesNames.index('Discrete'), pyMtsf.StandardCategoryNames.index(pyMtsf.CategoryMapping['Real']), None, 0)

    # Alias
    for var in fmi.scalarVariables.values():
        if var.alias is None or var.alias.lower() == "noalias":
            var.alias = 'NOAlias'  # To guarantee that this variable is the first
                                    # one in sorted order
    referenceList = [(x, y.valueReference, y.alias) for x, y in fmi.scalarVariables.iteritems()]
    referenceList.sort(key=itemgetter(2))
    referenceList.sort(key=itemgetter(1))

    for index in xrange(len(referenceList)):
        variableName = referenceList[index][0]
        if referenceList[index][2] in ['alias', 'negatedAlias']:
            valueReference = referenceList[index][1]
            prevValueReference = referenceList[index - 1][1]
            if prevValueReference != valueReference:
                raise ValueError("No original variable found for alias " + variableName)
            if referenceList[index - 1][2] == "NOAlias":
                originName = referenceList[index - 1][0]
            else:
                originName = fmi.scalarVariables[referenceList[index - 1][0]].aliasName
            fmi.scalarVariables[variableName].aliasName = originName
        else:
            fmi.scalarVariables[variableName].aliasName = None

    # Types and display units
    uniqueSimpleType = []
    for fmiVariableName, fmiVariable in fmi.scalarVariables.iteritems():
        type = fmiVariable.type
        unitList = [_None2Str(type.unit) + _None2Str(type.displayUnit)]
        if fmi.units.has_key(type.unit):
            for displayUnitName, displayUnit in fmi.units[type.unit].iteritems():
                if displayUnitName != type.unit:
                    unitList.append(displayUnitName + '{:.16e}'.format(displayUnit.gain) + '{:.16e}'.format(displayUnit.offset))
            # unitList.sort()
        dataType = type.type
        enumerations = ''
        if dataType == 'Enumeration':
            enumerations = ''.join([_None2Str(x[0]) + _None2Str(x[1]) for x in type.item])
        uniqueSimpleType.append((fmiVariableName, type, _None2Str(type.name) + str(pyMtsf.DataType[dataType]) + _None2Str(type.quantity) + str(type.relativeQuantity), ''.join(unitList), enumerations))

    # Simple Types
    uniqueSimpleType.sort(key=itemgetter(3))
    uniqueSimpleType.sort(key=itemgetter(2))
    lastUniqueStr = ''
    rowIndex = dict()
    lastIndex = -1
    uniqueDisplayUnit = []
    uniqueEnumerations = []
    for s in uniqueSimpleType:
        fmiVariableName = s[0]
        type = s[1]
        uniqueStr = s[2] + s[3] + s[4]
        if uniqueStr == lastUniqueStr:
            rowIndex[fmiVariableName] = lastIndex
        else:
            lastUniqueStr = uniqueStr
            lastIndex += 1
            rowIndex[fmiVariableName] = lastIndex
            uniqueDisplayUnit.append((type, lastIndex, s[3]))
            uniqueEnumerations.append((type, lastIndex, s[4]))
            dataType = type.type
            simpleTypes.append(pyMtsf.SimpleType(type.name, pyMtsf.DataType[dataType], type.quantity, type.relativeQuantity, -1, type.description))

    # Units
    uniqueDisplayUnit.sort(key=itemgetter(2))
    lastUniqueStr = ''
    startRow = -1
    for s in uniqueDisplayUnit:
        type = s[0]
        k = s[1]
        uniqueStr = s[2]
        if uniqueStr == lastUniqueStr:
            simpleTypes[k].unitOrEnumerationRow = startRow
        else:
            lastUniqueStr = uniqueStr
            if uniqueStr != '':  # There is a unit definition
                startRow = len(units)
                units.append(pyMtsf.Unit(type.unit, 1.0, 0.0, 0))
                if fmi.units.has_key(type.unit):
                    for displayUnitName, displayUnit in fmi.units[type.unit].iteritems():
                        if displayUnitName != type.unit:
                            if type.displayUnit is not None and type.displayUnit != '' and type.displayUnit == displayUnitName:
                                mode = 2  # DefaultDisplayUnit
                            else:
                                mode = 1  # DisplayUnit
                            units.append(pyMtsf.Unit(displayUnitName, displayUnit.gain, displayUnit.offset, mode))

                simpleTypes[k].unitOrEnumerationRow = startRow
            else:
                startRow = -1

    # Enumerations
    uniqueEnumerations.sort(key=itemgetter(2))
    lastUniqueStr = ''
    startRow = -1
    for s in uniqueEnumerations:
        type = s[0]
        k = s[1]
        uniqueStr = s[2]
        if uniqueStr != '':
            if uniqueStr == lastUniqueStr:
                simpleTypes[k].unitOrEnumerationRow = startRow
            else:
                lastUniqueStr = uniqueStr
                startRow = len(enumerationsMatrix)
                j = 0
                for enum in type.item:
                    j += 1
                    if j == 1:
                        firstEntry = 1
                    else:
                        firstEntry = 0
                    enumerationsMatrix.append(pyMtsf.Enumeration(enum[0], j, enum[1], firstEntry))
                simpleTypes[k].unitOrEnumerationRow = startRow

    # Iterate over all fmi-variables
    for fmiVariableName, fmiVariable in fmi.scalarVariables.iteritems():
        variableType = fmiVariable.type.type
        if variableType != "String":  # Do not support strings
            variability = fmiVariable.variability

            aliasNegated = 0
            aliasName = fmiVariable.aliasName
            if aliasName is not None:
                if fmiVariable.alias == 'negatedAlias':
                    aliasNegated = 1
                # Due to possibly insufficient information in xml-file
                variability = fmi.scalarVariables[aliasName].variability
            categoryIndex = pyMtsf.StandardCategoryNames.index(pyMtsf.CategoryMapping[variableType])
            if variability in ['constant', 'parameter']:
                seriesIndex = allSeriesNames.index('Fixed')
            elif variability == 'discrete':
                seriesIndex = allSeriesNames.index('Discrete')
            else:
                seriesIndex = allSeriesNames.index('Continuous')

            causality = fmiVariable.causality
            # Due to FMI 1.0; in vers. 2.0 this should not be necessary
            if causality is None:
                causality = 'local'
            if variability == 'parameter':
                causality = 'parameter'
                variability = 'fixed'
            if causality in ['internal', 'none']:
                causality = 'local'

            simpleTypeRow = rowIndex[fmiVariableName]
            variable[fmiVariableName] = pyMtsf.ScalarModelVariable(fmiVariable.description,
                                                    causality,
                                                    simpleTypeRow,
                                                    variability,
                                                    seriesIndex, categoryIndex,
                                                    aliasName, aliasNegated)

    # Some basics for independent time variables
    startRow = len(units)
    units.append(pyMtsf.Unit('s', 1.0, 0.0, 0))
    units.append(pyMtsf.Unit('ms', 0.001, 0.0, 1))
    units.append(pyMtsf.Unit('min', 60.0, 0.0, 1))
    units.append(pyMtsf.Unit('h', 3600.0, 0.0, 1))
    units.append(pyMtsf.Unit('d', 86400.0, 0.0, 1))

    simpleTypes.append(pyMtsf.SimpleType('Time', pyMtsf.DataType["Real"], 'Time', False, startRow, ''))
    variable['Time'].simpleTypeRow = len(simpleTypes) - 1
    variable['TimeDiscrete'].simpleTypeRow = len(simpleTypes) - 1

    modelDescription = pyMtsf.ModelDescription(fmi.modelName, fmi.description, fmi.author, fmi.version, fmi.generationTool, fmi.generationDateAndTime, fmi.variableNamingConvention)
    modelVariables = pyMtsf.ModelVariables(variable, StandardSeriesForFmi, pyMtsf.StandardCategoryNames)

    return modelDescription, modelVariables, simpleTypes, units, enumerationsMatrix
Exemplo n.º 2
0
def convertFromDymolaMatFile(matFilename, mtsfFilename=None):
    ''' Converts a Dymola result file (in mat-format) into the MTSF format.
        Returns the filename of the new result file
    '''

    # Define file name of result file
    if mtsfFilename is None:
        if len(matFilename) >= 4:
            if matFilename[-4:] == '.mat':
                resultFileName = matFilename[:-4] + '.mtsf'
            else:
                resultFileName = matFilename + '.mtsf'
        else:
            resultFileName = matFilename + '.mtsf'
    else:
        if '.mtsf' in mtsfFilename:
            if mtsfFilename[-5:] == '.mtsf':
                resultFileName = mtsfFilename
            else:
                resultFileName = mtsfFilename + '.mtsf'
        else:
            resultFileName = mtsfFilename + '.mtsf'

    from ..DymolaMat import DymolaMat

    # Load mat-file
    res = DymolaMat.Results(matFilename)

    # Define basic structure of result file
    variable = collections.OrderedDict()

    # Search for aliases
    sortedVariables = [(i, res._dataInfo[i, 0], abs(res._dataInfo[i, 1]))
                       for i in xrange(len(res._name))]
    sortedVariables.sort(key=itemgetter(2))
    sortedVariables.sort(key=itemgetter(1))
    aliasName = [None for i in xrange(len(res._name))]
    for i, var in enumerate(sortedVariables):
        index = var[0]
        alias = None
        j = i
        while j > 0:
            if sortedVariables[j - 1][1] != var[1] or sortedVariables[
                    j - 1][2] != var[2]:
                break
            else:
                j -= 1
        if j < i:
            alias = res._name[sortedVariables[j][0]]
        aliasName[index] = alias
    dataIndexFixed = []
    dataIndexContinuous = []
    categoryIndex = pyMtsf.StandardCategoryNames.index(
        pyMtsf.CategoryMapping['Real'])
    for index, variableName in enumerate(res._name):
        aliasNegated = False
        if res._dataInfo[index, 0] == 1:
            variability = 'fixed'
            seriesIndex = 0  # Fixed
        else:
            variability = 'continuous'
            seriesIndex = 1  # Continuous
        if res._dataInfo[index, 1] < 0:
            aliasNegated = True
        if aliasName[index] is None:
            if variability == 'fixed':
                dataIndexFixed.append(abs(res._dataInfo[index, 1]) - 1)
            else:
                dataIndexContinuous.append(abs(res._dataInfo[index, 1]) - 1)
        variable[variableName] = pyMtsf.ScalarModelVariable(
            res._description[index],
            'option',
            0,  # may be set later
            variability,
            seriesIndex,
            categoryIndex,
            aliasName[index],
            aliasNegated)
    modelVariables = pyMtsf.ModelVariables(variable,
                                           MtsfFmi.StandardSeriesForFmi,
                                           pyMtsf.StandardCategoryNames)
    timeData = res.data("Time")
    modelVariables.allSeries[1].initialRows = len(timeData)  # Continuous
    simpleTypes = []
    units = []
    enumerations = []
    simpleTypes.append(
        pyMtsf.SimpleType('Real without unit', pyMtsf.DataType["Real"], '',
                          False, -1, ''))  # No unit

    unitList = [(index, unit) for index, unit in enumerate(res._unit)]
    unitList.sort(key=itemgetter(1))
    preUnit = ''
    for x in unitList:
        index = x[0]
        unit = x[1]
        if unit != '':
            if preUnit != unit:
                units.append(pyMtsf.Unit(unit, 1.0, 0.0, 0))
                simpleTypes.append(
                    pyMtsf.SimpleType('Real, Unit = ' + unit,
                                      pyMtsf.DataType["Real"], '', False,
                                      len(units) - 1, ''))
                preUnit = unit
                modelVariables.variable[
                    res._name[index]].simpleTypeRow = len(simpleTypes) - 1
            else:
                modelVariables.variable[
                    res._name[index]].simpleTypeRow = len(simpleTypes) - 1
    experimentSetup = pyMtsf.ExperimentSetup(
        startTime=timeData[0],
        stopTime=timeData[-1],
        algorithm="",
        relativeTolerance='',
        author="",
        description="",
        generationDateAndTime=time.strftime("%a, %d %b %Y %H:%M:%S",
                                            time.gmtime()),
        generationTool="Python",
        machine=os.getenv('COMPUTERNAME'),
        cpuTime="")
    modelDescription = pyMtsf.ModelDescription(resultFileName[:-5], '', '', '',
                                               '', '', 'structured')
    # Create result object
    mtsf = pyMtsf.MTSF(resultFileName, modelDescription, modelVariables,
                       experimentSetup, simpleTypes, units, enumerations)
    # Write numeric data
    fixedValues = numpy.ndarray((len(dataIndexFixed, )))
    for i, index in enumerate(dataIndexFixed):
        fixedValues[i] = res._data[0][0, index]
    continuousValues = numpy.ndarray((len(timeData), len(dataIndexContinuous)))
    for i, index in enumerate(dataIndexContinuous):
        continuousValues[:, i] = res._data[1][:, index]
    mtsf.results.series['Fixed'].category[
        pyMtsf.CategoryMapping['Real']].writeData(fixedValues)
    mtsf.results.series['Continuous'].category[
        pyMtsf.CategoryMapping['Real']].writeData(continuousValues)

    # Close file
    mtsf.close()
    return resultFileName
Exemplo n.º 3
0
def convertFromFmi(fmuFilename, fmi=None):
    ''' Returns data to initialize an MTSF result file from an FMU.
        The call to initialize an MTSF result file is
            pyMtsf.MTSF(resultFileName, modelDescription, modelVariables, experimentSetup, simpleTypes, units, enumerationsMatrix)
        The missing data is resultFileName and experimentSetup to be specified before initializing the MTSF object.

        Inputs                       Type:
            fmuFilename              String
            fmi                      FMIDescription      [optional]
            if fmi is given, then fmuFilename is ignored. Otherwise the FMI description is loaded from the given file.

        Outputs
           modelDescription          pyMtsf.ModelDescription
           modelVariables            pyMtsf.ModelVariables
           simpleTypes               list of pyMtsf.SimpleType
           units                     list of pyMtsf.Unit
           enumerationsMatrix        list of pyMtsf.Enumeration
    '''
    def _None2Str(x):
        if x is None:
            return ''
        else:
            return x

    # Load FMIDescription if necessary
    if fmi is None:
        fmuFile = zipfile.ZipFile(
            os.path.join(os.getcwd(), fmuFilename + u'.fmu'), 'r')
        fmi = FMIDescription(fmuFile.open('modelDescription.xml'))

    # Prepare some variables
    allSeriesNames = [x.name for x in StandardSeriesForFmi]
    variable = collections.OrderedDict()
    simpleTypes = []
    units = []
    enumerationsMatrix = []
    variable['Time'] = pyMtsf.ScalarModelVariable(
        'Continuous Time', 'input', 0, 'continuous',
        allSeriesNames.index('Continuous'),
        pyMtsf.StandardCategoryNames.index(pyMtsf.CategoryMapping['Real']),
        None, 0)
    variable['TimeDiscrete'] = pyMtsf.ScalarModelVariable(
        'Discrete Time at events', 'input', 0, 'discrete',
        allSeriesNames.index('Discrete'),
        pyMtsf.StandardCategoryNames.index(pyMtsf.CategoryMapping['Real']),
        None, 0)

    # Searching aliases
    referenceList = [(x, fmi.scalarVariables[x].valueReference)
                     for x in fmi.scalarVariables.keys()]
    referenceList.sort(key=itemgetter(1))
    alias = dict()
    if len(referenceList) > 1:
        origin = None
        alias[referenceList[0][0]] = None
        for index in xrange(len(referenceList) - 1):
            variableName = referenceList[index][0]
            valueReference = referenceList[index][1]
            nextVariableName = referenceList[index + 1][0]
            nextValueReference = referenceList[index + 1][1]
            if valueReference == nextValueReference:
                if origin is None:
                    origin = variableName
                alias[nextVariableName] = origin
            else:
                origin = None
                alias[nextVariableName] = None
    '''
    # Types and display units
    uniqueSimpleType = []
    for fmiVariableName, fmiVariable in fmi.scalarVariables.iteritems():
        type = fmiVariable.type
        unitList = [_None2Str(type.unit) + _None2Str(type.displayUnit)]
        if fmi.units.has_key(type.unit):
            for displayUnitName, displayUnit in fmi.units[type.unit].iteritems():
                if displayUnitName != type.unit:
                    unitList.append(displayUnitName + '{:.16e}'.format(displayUnit.factor) + '{:.16e}'.format(displayUnit.offset))
            # unitList.sort()
        dataType = type.basicType
        enumerations = ''
        if dataType == 'Enumeration':
            enumerations = ''.join([_None2Str(x[0]) + _None2Str(x[1]) for x in type.item])
        uniqueSimpleType.append((fmiVariableName, type, _None2Str(type.name) + str(pyMtsf.DataType[dataType]) + _None2Str(type.quantity) + str(type.relativeQuantity), ''.join(unitList), enumerations))
    
   
    
    # Simple Types
    uniqueSimpleType.sort(key=itemgetter(3))
    uniqueSimpleType.sort(key=itemgetter(2))
    lastUniqueStr = ''
    rowIndex = dict()
    lastIndex = -1
    uniqueDisplayUnit = []
    uniqueEnumerations = []
    for s in uniqueSimpleType:
        fmiVariableName = s[0]
        type = s[1]
        uniqueStr = s[2] + s[3] + s[4]
        if uniqueStr == lastUniqueStr:
            rowIndex[fmiVariableName] = lastIndex
        else:
            lastUniqueStr = uniqueStr
            lastIndex += 1
            rowIndex[fmiVariableName] = lastIndex
            uniqueDisplayUnit.append((type, lastIndex, s[3]))
            uniqueEnumerations.append((type, lastIndex, s[4]))
            dataType = type.type
            simpleTypes.append(pyMtsf.SimpleType(type.name, pyMtsf.DataType[dataType], type.quantity, type.relativeQuantity, -1, type.description))

    # Units
    uniqueDisplayUnit.sort(key=itemgetter(2))
    lastUniqueStr = ''
    startRow = -1
    for s in uniqueDisplayUnit:
        type = s[0]
        k = s[1]
        uniqueStr = s[2]
        if uniqueStr == lastUniqueStr:
            simpleTypes[k].unitOrEnumerationRow = startRow
        else:
            lastUniqueStr = uniqueStr
            if uniqueStr != '':  # There is a unit definition
                startRow = len(units)
                units.append(pyMtsf.Unit(type.unit, 1.0, 0.0, 0))
                if fmi.units.has_key(type.unit):
                    for displayUnitName, displayUnit in fmi.units[type.unit].iteritems():
                        if displayUnitName != type.unit:
                            if type.displayUnit is not None and type.displayUnit != '' and type.displayUnit == displayUnitName:
                                mode = 2  # DefaultDisplayUnit
                            else:
                                mode = 1  # DisplayUnit
                            units.append(pyMtsf.Unit(displayUnitName, displayUnit.gain, displayUnit.offset, mode))

                simpleTypes[k].unitOrEnumerationRow = startRow
            else:
                startRow = -1

    # Enumerations
    uniqueEnumerations.sort(key=itemgetter(2))
    lastUniqueStr = ''
    startRow = -1
    for s in uniqueEnumerations:
        type = s[0]
        k = s[1]
        uniqueStr = s[2]
        if uniqueStr != '':
            if uniqueStr == lastUniqueStr:
                simpleTypes[k].unitOrEnumerationRow = startRow
            else:
                lastUniqueStr = uniqueStr
                startRow = len(enumerationsMatrix)
                j = 0
                for enum in type.item:
                    j += 1
                    if j == 1:
                        firstEntry = 1
                    else:
                        firstEntry = 0
                    enumerationsMatrix.append(pyMtsf.Enumeration(enum[0], j, enum[1], firstEntry))
                simpleTypes[k].unitOrEnumerationRow = startRow

    '''

    simpleTypes.append(
        pyMtsf.SimpleType('Real', pyMtsf.DataType['Real'], 'Real', False, -1,
                          ''))
    simpleTypes.append(
        pyMtsf.SimpleType('Integer', pyMtsf.DataType['Integer'], 'Integer',
                          False, -1, ''))
    simpleTypes.append(
        pyMtsf.SimpleType('Boolean', pyMtsf.DataType['Boolean'], 'Boolean',
                          False, -1, ''))

    # Iterate over all fmi-variables
    for fmiVariableName, fmiVariable in fmi.scalarVariables.iteritems():
        variableType = fmiVariable.type.basicType
        if variableType != "String":  # Do not support strings
            aliasNegated = 0  # Not supported in FMI 2.0
            aliasName = alias[fmiVariableName]

            categoryIndex = pyMtsf.StandardCategoryNames.index(
                pyMtsf.CategoryMapping[variableType])

            variability = fmiVariable.variability
            if variability == 'tunable':
                variability = 'fixed'
            if variability in ['constant', 'fixed']:
                seriesIndex = allSeriesNames.index('Fixed')
            elif variability in ['discrete']:
                seriesIndex = allSeriesNames.index('Discrete')
            else:
                seriesIndex = allSeriesNames.index('Continuous')

            causality = fmiVariable.causality
            if causality == 'calculatedParameter':
                causality = 'parameter'
            if causality == 'independent':
                causality = 'option'

            if variableType == 'Real':
                simpleTypeRow = 0
            elif variableType == 'Integer':
                simpleTypeRow = 1
            elif variableType == 'Boolean':
                simpleTypeRow = 2
            elif variableType == 'Enumeration':
                simpleTypeRow = 1  # Integer

            variable[fmiVariableName] = pyMtsf.ScalarModelVariable(
                fmiVariable.description, causality, simpleTypeRow, variability,
                seriesIndex, categoryIndex, aliasName, aliasNegated)

    # Some basics for independent time variables
    startRow = len(units)
    units.append(pyMtsf.Unit('s', 1.0, 0.0, 0))
    units.append(pyMtsf.Unit('ms', 0.001, 0.0, 1))
    units.append(pyMtsf.Unit('min', 60.0, 0.0, 1))
    units.append(pyMtsf.Unit('h', 3600.0, 0.0, 1))
    units.append(pyMtsf.Unit('d', 86400.0, 0.0, 1))

    simpleTypes.append(
        pyMtsf.SimpleType('Time', pyMtsf.DataType["Real"], 'Time', False,
                          startRow, ''))
    variable['Time'].simpleTypeRow = len(simpleTypes) - 1
    variable['TimeDiscrete'].simpleTypeRow = len(simpleTypes) - 1

    modelDescription = pyMtsf.ModelDescription(
        _None2Str(fmi.modelName), _None2Str(fmi.description),
        _None2Str(fmi.author), _None2Str(fmi.version),
        _None2Str(fmi.generationTool), _None2Str(fmi.generationDateAndTime),
        fmi.variableNamingConvention)
    modelVariables = pyMtsf.ModelVariables(variable, StandardSeriesForFmi,
                                           pyMtsf.StandardCategoryNames)

    return modelDescription, modelVariables, simpleTypes, units, enumerationsMatrix