text: # python 2/3 compatibility
  from __future__ import division, print_function
  import sys
  import os.path
  import numpy
  import pandas
  import copy
  import json
  import jxmlease
  import xml.etree.ElementTree as ET
  import csv
  from sbtab import SBtab
  
  # package imports
  import rba
  from .data_block import DataBlock
  
  
  class RBA_SimulationData(object):
      """
      Class holding information on simulations with the model.
  
      Attributes
      ----------
      StructuralInformation : rbatools.rba_ModelStructure RBA_ModelStructure object.
           Model description
      SessionName : str
           Name of simulation session
      ProteinData : rbatools.data_block DataBlock object.
           Simulated protein levels
      ReactionData : rbatools.data_block DataBlock object.
           Simulated reaction data
      EnzymeData : rbatools.data_block DataBlock object.
           Simulated enzyme data
      ProcessData : rbatools.data_block DataBlock object.
           Simulated process machinery data
      MetaboliteConstraintData : rbatools.data_block DataBlock object.
           Simulation information on mass-balance constraints
      DensityConstraintData : rbatools.data_block DataBlock object.
           Simulation information on compartment-density constraints
      ProcessConstraintData : rbatools.data_block DataBlock object.
           Simulation information on process-capacity constraints
      EnzymeConstraintData : rbatools.data_block DataBlock object.
           Simulation information on enzyme-efficiency constraints
  
      Methods
      ----------
      __init__(StaticData)
          Initiates Simulation data object
  
      fromSimulationResults(Controller, session_name)
          Imports data from rbatools.RBA_Controler object
  
      fromJSON(inputString)
          Imports data from JSON string object
  
      toXML()
          Exports xml-file
  
      toJSON()
          Returns simulation data as JSON string
  
      exportSBtab()
          Exports SBtab files
  
      exportSBtab_OneFile()
          Exports simulation data in one single sbtab file
  
      exportCSV(deleteZerosRows=True)
          Exports simulation data as csv files
  
      exportEscherMap(type='fluxes')
          Exports input file for generation of Escher maps.
  
      exportProteoMap()
          Exports input file for the generation of Proteo maps from
          simulation data.
      """
  
      def __init__(self, StaticData):
          """
          Initiates Simulation data object
  
          Parameters
          ----------
          StaticData : rbatools.RBA_ModelStructure
          """
  
          self.StructuralInformation = copy.deepcopy(StaticData)
  
          self.ProteinData = DataBlock()
          self.ProtoProteinData = DataBlock()
          self.ReactionData = DataBlock()
          self.ExchangeData = DataBlock()
          self.uniqueReactionData = DataBlock()
          self.EnzymeData = DataBlock()
          self.ProcessData = DataBlock()
          self.MetaboliteConstraintData = DataBlock()
          self.DensityConstraintData = DataBlock()
          self.EnzymeConstraintData = DataBlock()
          self.ProcessConstraintData = DataBlock()
          self.GeneralRunInfo = DataBlock()
          self.ObjectiveFunctionInfo = DataBlock()
  
          self.SessionName = ''
  
          self.ProteinData.fromDict({})
          self.ProtoProteinData.fromDict({})
          self.ReactionData.fromDict({})
          self.ExchangeData.fromDict({})
          self.uniqueReactionData.fromDict({})
          self.EnzymeData.fromDict({})
          self.ProcessData.fromDict({})
          self.MetaboliteConstraintData.fromDict({})
          self.DensityConstraintData.fromDict({})
          self.EnzymeConstraintData.fromDict({})
          self.ProcessConstraintData.fromDict({})
          self.GeneralRunInfo.fromDict({})
          self.ObjectiveFunctionInfo.fromDict({})
  
      def fromSimulationResults(self, Controller, session_name=''):
          """
          Imports data from rbatools.RBA_Controler object
  
          Parameters
          ----------
          Controller : rbatools.RBA_newControler
              Defines from which object to extract the data from
          session_name: str
              Defines the name of the session
              Is appended to the filenames generated by export methods.
          """
          self.SessionName = session_name
  
          self.run_names = list(Controller.Results['ObjectiveValue'])
          ObjDict = {}
          for run in list(Controller.Results['ObjectiveValue']):
              ObjDict.update({run: Controller.Results['ObjectiveValue'].loc['ObjectiveValue', run]})
  
          SolutionType_Dict = {}
          for run in list(Controller.Results['SolutionType']):
              SolutionType_Dict.update(
                  {run: Controller.Results['SolutionType'].loc['SolutionType', run]})
  
          MuDict = {}
          for run in list(Controller.Results['Mu']):
              MuDict.update({run: Controller.Results['Mu'].loc['Mu', run]})
  
          self.GeneralRunInfo.addEntries({'ProblemType': SolutionType_Dict})
          self.GeneralRunInfo.addEntries({'Mu': MuDict})
          self.GeneralRunInfo.addEntries({'Obj_Val': ObjDict})
  
          for var in list(Controller.Results['ObjectiveFunction'].index):
              if var not in self.ObjectiveFunctionInfo.Elements:
                  self.ObjectiveFunctionInfo.Elements.update({var: {}})
              for run in list(Controller.Results['ObjectiveFunction']):
                  self.ObjectiveFunctionInfo.Elements[var].update(
                      {run: Controller.Results['ObjectiveFunction'].loc[var, run]})
  
          for exchange in list(Controller.Results['ExchangeFluxes'].index):
              if exchange not in self.ExchangeData.Elements:
                  self.ExchangeData.Elements.update({exchange: {}})
  #            self.ExchangeData.Elements[exchange].update({'ID': exchange})
              for run in list(Controller.Results['ExchangeFluxes']):
                  self.ExchangeData.Elements[exchange].update(
                      {run: Controller.Results['ExchangeFluxes'].loc[exchange, run]})
  
          for reaction in list(Controller.Results['Reactions'].index):
              if reaction not in self.ReactionData.Elements:
                  self.ReactionData.Elements.update({reaction: {}})
  #            self.ReactionData.Elements[reaction].update({'ID': reaction})
              for run in list(Controller.Results['Reactions']):
                  self.ReactionData.Elements[reaction].update(
                      {run: Controller.Results['Reactions'].loc[reaction, run]})
  
          for reaction in list(Controller.Results['uniqueReactions'].index):
              if reaction not in self.uniqueReactionData.Elements:
                  self.uniqueReactionData.Elements.update({reaction: {}})
  #            self.uniqueReactionData.Elements[reaction].update({'ID': reaction})
              for run in list(Controller.Results['uniqueReactions']):
                  self.uniqueReactionData.Elements[reaction].update(
                      {run: Controller.Results['uniqueReactions'].loc[reaction, run]})
  
          for enzyme in list(Controller.Results['Enzymes'].index):
              if enzyme not in self.EnzymeData.Elements:
                  self.EnzymeData.Elements.update({enzyme: {}})
  #            self.EnzymeData.Elements[enzyme].update({'ID': enzyme})
              for run in list(Controller.Results['Enzymes']):
                  self.EnzymeData.Elements[enzyme].update(
                      {run: Controller.Results['Enzymes'].loc[enzyme, run]})
  
          for process in list(Controller.Results['Processes'].index):
              if process not in self.ProcessData.Elements:
                  self.ProcessData.Elements.update({process: {}})
  #            self.ProcessData.Elements[process].update({'ID': process})
              for run in list(Controller.Results['Processes']):
                  self.ProcessData.Elements[process].update(
                      {run: Controller.Results['Processes'].loc[process, run]})
  
          for protein in list(Controller.Results['Proteins'].index):
              if protein not in self.ProteinData.Elements:
                  self.ProteinData.Elements.update({protein: {}})
  #            self.ProteinData.Elements[protein].update({'ID': protein})
              for run in list(Controller.Results['Proteins']):
                  self.ProteinData.Elements[protein].update(
                      {run: Controller.Results['Proteins'].loc[protein, run]})
  
          for protoprotein in list(Controller.Results['ProtoProteins'].index):
              if protoprotein not in self.ProtoProteinData.Elements:
                  self.ProtoProteinData.Elements.update({protoprotein: {}})
  #            self.ProtoProteinData.Elements[protoprotein].update({'ID': protoprotein})
              for run in list(Controller.Results['ProtoProteins']):
                  self.ProtoProteinData.Elements[protoprotein].update(
                      {run: Controller.Results['ProtoProteins'].loc[protoprotein, run]})
  
          for constr in list(Controller.Results['Constraints'].index):
              if constr in list(self.StructuralInformation.MetaboliteConstraintsInfo.Elements.keys()):
                  if constr not in self.MetaboliteConstraintData.Elements:
                      self.MetaboliteConstraintData.Elements.update({constr: {}})
  #                self.MetaboliteConstraintData.Elements[constr].update({'ID': constr})
                  for run in list(Controller.Results['Constraints']):
                      self.MetaboliteConstraintData.Elements[constr].update(
                          {run: Controller.Results['Constraints'].loc[constr, run]})
              if constr in list(self.StructuralInformation.DensityConstraintsInfo.Elements.keys()):
                  if constr not in self.DensityConstraintData.Elements:
                      self.DensityConstraintData.Elements.update({constr: {}})
  #                self.DensityConstraintData.Elements[constr].update({'ID': constr})
                  for run in list(Controller.Results['Constraints']):
                      self.DensityConstraintData.Elements[constr].update(
                          {run: Controller.Results['Constraints'].loc[constr, run]})
              if constr in list(self.StructuralInformation.EnzymeConstraintsInfo.Elements.keys()):
                  if constr not in self.EnzymeConstraintData.Elements:
                      self.EnzymeConstraintData.Elements.update({constr: {}})
  #                self.EnzymeConstraintData.Elements[constr].update({'ID': constr})
                  for run in list(Controller.Results['Constraints']):
                      self.EnzymeConstraintData.Elements[constr].update(
                          {run: Controller.Results['Constraints'].loc[constr, run]})
              if constr in list(self.StructuralInformation.ProcessConstraintsInfo.Elements.keys()):
                  if constr not in self.ProcessConstraintData.Elements:
                      self.ProcessConstraintData.Elements.update({constr: {}})
  #                self.ProcessConstraintData.Elements[constr].update({'ID': constr})
                  for run in list(Controller.Results['Constraints']):
                      self.ProcessConstraintData.Elements[constr].update(
                          {run: Controller.Results['Constraints'].loc[constr, run]})
  
      def fromJSON(self, inputString):
          """
          Imports data from JSON string object
  
          Parameters
          ----------
          inputString: json-string
          """
  
          Block = json.loads(inputString)
          self.ReactionData = DataBlock()
          self.ProteinData = DataBlock()
          self.EnzymeData = DataBlock()
          self.ProcessData = DataBlock()
          self.MetaboliteConstraintData = DataBlock()
          self.DensityConstraintData = DataBlock()
          self.EnzymeConstraintData = DataBlock()
          self.ProcessConstraintData = DataBlock()
          self.ReactionData.fromDict(Block['ReactionData'])
          self.ProteinData.fromDict(Block['ProteinData'])
          self.EnzymeData.fromDict(Block['EnzymeData'])
          self.ProcessData.fromDict(Block['ProcessData'])
          self.MetaboliteConstraintData.fromDict(Block['MetaboliteConstraintData'])
          self.DensityConstraintData.fromDict(Block['DensityConstraintData'])
          self.EnzymeConstraintData.fromDict(Block['EnzymeConstraintData'])
          self.ProcessConstraintData.fromDict(Block['ProcessConstraintData'])
  
      def exportXML(self):
          """
          Exports xml-file
          """
  
          x = htmlStyle(self)
          root = ET.fromstring(jxmlease.emit_xml(x, encoding='utf-8'))
          m = ET.tostring(root, 'utf-8')
          return(m)
  
      def exportSBtab(self, filename=None, add_links=False, rba=False):
          """
          Exports simulation data in one single sbtab file
          """
          GeneralRunInfoTable = self.GeneralRunInfo.toSBtab(
              table_id='run_information', table_type='QuantityMatrix', table_name='Run information')
          GeneralRunInfoTable.filename = 'RunInfo.tsv'
          GeneralRunInfoTable.change_attribute(
              'Text', 'Growth rates mu and cellular objective values (by default: minimisation of total enzyme concentration).')
          #GeneralRunInfoTable.unset_attribute('Date')
          GeneralRunInfoTable.unset_attribute('SBtabVersion')
  
          ObjectiveFunctionDataTable = self.ObjectiveFunctionInfo.toSBtab(
              table_id='objective_coefficients', table_type='QuantityMatrix', table_name='Linear objective')
          ObjectiveFunctionDataTable.filename = 'ObjectiveFunctionData.tsv'
          ObjectiveFunctionDataTable.change_attribute('Unit', '')
          ObjectiveFunctionDataTable.change_attribute('QuantityType', 'objective_coefficient')
          ObjectiveFunctionDataTable.change_attribute(
              'Text', 'Coefficients in objective function (<0 : maximisation , >0 : minimisation)')
          #ObjectiveFunctionDataTable.unset_attribute('Date')
          ObjectiveFunctionDataTable.unset_attribute('SBtabVersion')
  
          ReactionDataTable = self.ReactionData.toSBtab(
              table_id='reaction_flux', table_type='QuantityMatrix', table_name='Reaction fluxes')
          ReactionDataTable.filename = 'ReactionData.tsv'
          ReactionDataTable.change_attribute('Unit', 'mmol/(h*gDW)')
          ReactionDataTable.change_attribute('QuantityType', 'reaction_flux')
          ReactionDataTable.change_attribute(
              'Text', 'Reaction fluxes obtained in the simulation runs (table columns).')
          #ReactionDataTable.unset_attribute('Date')
          ReactionDataTable.unset_attribute('SBtabVersion')
  
          EnzymeDataTable = self.EnzymeData.toSBtab(
              table_id='enzyme_concentration', table_type='QuantityMatrix', table_name='Enzyme concentrations')
          EnzymeDataTable.filename = 'EnzymeData.tsv'
          EnzymeDataTable.change_attribute('Unit', 'mmol/gDW')
          EnzymeDataTable.change_attribute('QuantityType', 'enzyme_concentration')
          EnzymeDataTable.change_attribute(
              'Text', 'Enzyme concentrations obtained in the simulation runs (table columns).')
          #EnzymeDataTable.unset_attribute('Date')
          EnzymeDataTable.unset_attribute('SBtabVersion')
  
          ProcessDataTable = self.ProcessData.toSBtab(
              table_id='machine_concentration', table_type='QuantityMatrix', table_name='Machine concentrations')
          ProcessDataTable.filename = 'ProcessData.tsv'
          ProcessDataTable.change_attribute('Unit', 'mmol/gDW')
          ProcessDataTable.change_attribute('QuantityType', 'machine_concentration')
          ProcessDataTable.change_attribute(
              'Text', 'Macromolecular machine concentrations obtained in the simulation runs (table columns).')
          #ProcessDataTable.unset_attribute('Date')
          ProcessDataTable.unset_attribute('SBtabVersion')
  
          ProteinDataTable = self.ProteinData.toSBtab(
              table_id='protein_concentration', table_type='QuantityMatrix', table_name='Protein concentrations')
          ProteinDataTable.filename = 'ProteinData.tsv'
          ProteinDataTable.change_attribute('Unit', 'mmol/gDW')
          ProteinDataTable.change_attribute('QuantityType', 'protein_concentration')
          ProteinDataTable.change_attribute(
              'Text', 'Protein concentrations obtained in the simulation runs (table columns).')
          #ProteinDataTable.unset_attribute('Date')
          ProteinDataTable.unset_attribute('SBtabVersion')
  
          MetaboliteConstraintDataTable = self.MetaboliteConstraintData.toSBtab(
              table_id='metabolite_mass_balance_dual', table_type='QuantityMatrix', table_name='Metabolite mass-balance dual values')
          MetaboliteConstraintDataTable.filename = 'MetaboliteConstraintData.tsv'
          MetaboliteConstraintDataTable.change_attribute('Unit', '')
          MetaboliteConstraintDataTable.change_attribute('QuantityType', 'lagrange_multiplier')
          MetaboliteConstraintDataTable.change_attribute(
              'Text', 'Shadow prices of the metabolite mass-balance constraints obtained in the simulation runs (table columns). The measurement units of shadow prices are given by the measurement unit of objective function, divided by the measurement units of the respective constraints')
          #MetaboliteConstraintDataTable.unset_attribute('Date')
          MetaboliteConstraintDataTable.unset_attribute('SBtabVersion')
  
          DensityConstraintDataTable = self.DensityConstraintData.toSBtab(
              table_id='density_constraint_dual', table_type='QuantityMatrix', table_name='Compartment density dual values')
          DensityConstraintDataTable.filename = 'DensityConstraintData.tsv'
          DensityConstraintDataTable.change_attribute('QuantityType', 'lagrange_multiplier')
          DensityConstraintDataTable.change_attribute('Unit', '')
          DensityConstraintDataTable.change_attribute(
              'Text', 'Shadow prices of the density constraints obtained in the simulation runs (table columns). The measurement units of shadow prices are given by the measurement unit of objective function, divided by the measurement units of the respective constraints')
          #DensityConstraintDataTable.unset_attribute('Date')
          DensityConstraintDataTable.unset_attribute('SBtabVersion')
  
          EnzymeConstraintDataTable = self.EnzymeConstraintData.toSBtab(
              table_id='enzyme_capacity_dual', table_type='QuantityMatrix', table_name='Enzyme capacity dual values')
          EnzymeConstraintDataTable.filename = 'EnzymeConstraintData.tsv'
          EnzymeConstraintDataTable.change_attribute('QuantityType', 'lagrange_multiplier')
          EnzymeConstraintDataTable.change_attribute('Unit', '')
          EnzymeConstraintDataTable.change_attribute(
              'Text', 'Shadow prices of the enzyme-capacity constraints obtained in the simulation runs (table columns). The measurement units of shadow prices are given by the measurement unit of objective function, divided by the measurement units of the respective constraints')
          #EnzymeConstraintDataTable.unset_attribute('Date')
          EnzymeConstraintDataTable.unset_attribute('SBtabVersion')
  
          ProcessConstraintDataTable = self.ProcessConstraintData.toSBtab(
              table_id='machine_capacity_dual', table_type='QuantityMatrix', table_name='Machine capacity dual values')
          ProcessConstraintDataTable.filename = 'ProcessConstraintData.tsv'
          ProcessConstraintDataTable.change_attribute('Unit', '')
          ProcessConstraintDataTable.change_attribute('QuantityType', 'lagrange_multiplier')
          ProcessConstraintDataTable.change_attribute(
              'Text', 'Shadow prices of the machine-capacity constraints obtained in the simulation runs (table columns). The measurement units of shadow prices are given by the measurement unit of objective function, divided by the measurement units of the respective constraints')
          #ProcessConstraintDataTable.unset_attribute('Date')
          ProcessConstraintDataTable.unset_attribute('SBtabVersion')
  
          if filename is not None:
              filename_SBtab = filename
          else:
              filename_SBtab = 'RBA_results'
  
          if add_links:
              ReactionDataTable.add_column(column_list=['!ElementID']+[str('(!'+'Reaction/'+entry+'!)')
                                                                       for entry in list(ReactionDataTable.to_data_frame()['ID'])], position=1)
              ProcessDataTable.add_column(column_list=['!ElementID']+[str('(!'+'Process/'+entry+'!)')
                                                                      for entry in list(ProcessDataTable.to_data_frame()['ID'])], position=1)
              EnzymeDataTable.add_column(column_list=['!ElementID']+[str('(!'+'Enzyme/'+entry+'!)')
                                                                     for entry in list(EnzymeDataTable.to_data_frame()['ID'])], position=1)
              ProteinDataTable.add_column(column_list=['!ElementID']+[str('(!'+'Protein/'+entry+'!)')
                                                                      for entry in list(ProteinDataTable.to_data_frame()['ID'])], position=1)
              MetaboliteConstraintDataTable.add_column(column_list=['!ElementID']+[str(
                  '(!'+'Compound/'+entry+'!)') for entry in list(MetaboliteConstraintDataTable.to_data_frame()['ID'])], position=1)
              DensityConstraintDataTable.add_column(column_list=['!ElementID']+[str(
                  '(!'+'Compartment/'+entry+'!)') for entry in list(DensityConstraintDataTable.to_data_frame()['ID'])], position=1)
              ProcessConstraintDataTable.add_column(column_list=['!ElementID']+[str(
                  '(!'+'Process/'+entry+'!)') for entry in list(ProcessConstraintDataTable.to_data_frame()['ID'])], position=1)
              EnzymeConstraintDataTable.add_column(column_list=['!ElementID']+[str(
                  '(!'+'Enzyme/'+entry+'!)') for entry in list(EnzymeConstraintDataTable.to_data_frame()['ID'])], position=1)
  
              filename_SBtab += '_HTML'
  
          else:
              ReactionDataTable.add_column(
                  column_list=['!ElementID']+list(ReactionDataTable.to_data_frame(rba=rba)['ID']), position=1)
              ProcessDataTable.add_column(
                  column_list=['!ElementID']+list(ProcessDataTable.to_data_frame(rba=rba)['ID']), position=1)
              EnzymeDataTable.add_column(
                  column_list=['!ElementID']+list(EnzymeDataTable.to_data_frame(rba=rba)['ID']), position=1)
              ProteinDataTable.add_column(
                  column_list=['!ElementID']+list(ProteinDataTable.to_data_frame(rba=rba)['ID']), position=1)
              MetaboliteConstraintDataTable.add_column(
                  column_list=['!ElementID']+list(MetaboliteConstraintDataTable.to_data_frame(rba=rba)['ID']), position=1)
              DensityConstraintDataTable.add_column(
                  column_list=['!ElementID']+list(DensityConstraintDataTable.to_data_frame(rba=rba)['ID']), position=1)
              ProcessConstraintDataTable.add_column(
                  column_list=['!ElementID']+list(ProcessConstraintDataTable.to_data_frame(rba=rba)['ID']), position=1)
              EnzymeConstraintDataTable.add_column(
                  column_list=['!ElementID']+list(EnzymeConstraintDataTable.to_data_frame(rba=rba)['ID']), position=1)
  
  
          ReactionDataTable.remove_column(position=2)
          ProcessDataTable.remove_column(position=2)
          EnzymeDataTable.remove_column(position=2)
          ProteinDataTable.remove_column(position=2)
          MetaboliteConstraintDataTable.remove_column(position=2)
          DensityConstraintDataTable.remove_column(position=2)
          ProcessConstraintDataTable.remove_column(position=2)
          EnzymeConstraintDataTable.remove_column(position=2)
  
          self.Out = SBtab.SBtabDocument(name='rbatools_SimulationData_withLinks',
                                    sbtab_init=None, filename=str(filename_SBtab+'.tsv'))
          self.Out.add_sbtab(GeneralRunInfoTable)
          self.Out.add_sbtab(ObjectiveFunctionDataTable)
          self.Out.add_sbtab(ReactionDataTable)
          self.Out.add_sbtab(EnzymeDataTable)
          self.Out.add_sbtab(ProcessDataTable)
          self.Out.add_sbtab(ProteinDataTable)
          self.Out.add_sbtab(MetaboliteConstraintDataTable)
          self.Out.add_sbtab(DensityConstraintDataTable)
          self.Out.add_sbtab(EnzymeConstraintDataTable)
          self.Out.add_sbtab(ProcessConstraintDataTable)
  
          self.Out.change_attribute('DocumentName', 'RBA data')
          self.Out.name = filename
          self.Out.change_attribute('DocumentType', 'rba-simulation-data')
          self.Out.write()
      
      def getSBtabDoc(self):
          return self.Out
  
      def exportJSON(self):
          """
          Returns simulation data as JSON string
  
          Returns
          -------
          JSON string
          """
  
          Block = {'ReactionData': self.ReactionData.Elements,
                   'ProteinData': self.ProteinData.Elements,
                   'EnzymeData': self.EnzymeData.Elements,
                   'ProcessData': self.ProcessData.Elements,
                   'MetaboliteConstraintData': self.MetaboliteConstraintData.Elements,
                   'DensityConstraintData': self.DensityConstraintData.Elements,
                   'EnzymeConstraintData': self.EnzymeConstraintData.Elements,
                   'ProcessConstraintData': self.ProcessConstraintData.Elements}
          return(json.dumps(Block))
  
      def exportCSV(self, deleteZerosRows=True):
          """
          Exports simulation data as csv files
  
          Parameters
          ----------
          deleteZerosRows: bool
              Boolean wheter to remove rows which have only zero entries.
              (e.g. reactions which never carry flux in all runs)
              Default: True
          """
          self.csvs = {}
          exchange_data_csv = ''
          if len(self.SessionName) > 0:
              filename = self.SessionName+'_ExchangeData.csv'
          else:
              filename = 'ExchangeData.csv'
          with open(filename, "w", newline='') as fp:
              wr = csv.writer(fp, dialect='excel')
              IDs = list(self.ExchangeData.Elements.keys())
              exchange_data_csv += ','.join(['']+list(self.ExchangeData.Elements[IDs[0]].keys()))+'\n'
              wr.writerow([None]+list(self.ExchangeData.Elements[IDs[0]].keys()))
              for i in list(IDs):
                  valuerow = list(self.ExchangeData.Elements[i].values())
                  valuerow2 = []
                  for j in valuerow:
                      if pandas.isna(j):
                          valuerow2.append(0)
                      else:
                          valuerow2.append(j)
                  if deleteZerosRows:
                      if not all(v == 0 for v in valuerow2):
                          row = [i]+valuerow2
                          exchange_data_csv += ','.join(map(str, row))+'\n'
                          wr.writerow(row)
                  else:
                      row = [i]+valuerow2
                      exchange_data_csv += ','.join(map(row))+'\n'
                      wr.writerow(row)
          fp.close()
          self.csvs['ExchangeData.csv'] = exchange_data_csv
  
          general_info_csv = ''
          if len(self.SessionName) > 0:
              filename = self.SessionName+'_GeneralInfo.csv'
          else:
              filename = 'GeneralInfo.csv'
          with open(filename, "w", newline='') as fp:
              wr = csv.writer(fp, dialect='excel')
              IDs = list(self.GeneralRunInfo.Elements.keys())
              general_info_csv += ','.join(['']+list(self.GeneralRunInfo.Elements[IDs[0]].keys()))+'\n'
              wr.writerow([None]+list(self.GeneralRunInfo.Elements[IDs[0]].keys()))
              for i in list(IDs):
                  valuerow = list(self.GeneralRunInfo.Elements[i].values())
                  if deleteZerosRows:
                      if not all(v == 0 for v in valuerow):
                          row = [i]+valuerow
                          general_info_csv += ','.join(map(str,row))+'\n'
                          wr.writerow(row)
                  else:
                      row = [i]+valuerow
                      general_info_csv += ','.join(map(str,row))+'\n'
                      wr.writerow(row)
          fp.close()
          self.csvs['GeneralInfo.csv'] = general_info_csv
  
          reaction_data_csv = ''
          if len(self.SessionName) > 0:
              filename = self.SessionName+'_ReactionData.csv'
          else:
              filename = 'ReactionData.csv'
          with open(filename, "w", newline='') as fp:
              wr = csv.writer(fp, dialect='excel')
              IDs = list(self.ReactionData.Elements.keys())
              reaction_data_csv += ','.join(['']+list(self.ReactionData.Elements[IDs[0]].keys()))+'\n'
              wr.writerow([None]+list(self.ReactionData.Elements[IDs[0]].keys()))
              for i in list(IDs):
                  valuerow = list(self.ReactionData.Elements[i].values())
                  if deleteZerosRows:
                      if not all(v == 0 for v in valuerow):
                          row = [i]+valuerow
                          reaction_data_csv += ','.join(map(str,row))+'\n'
                          wr.writerow(row)
                  else:
                      row = [i]+valuerow
                      reaction_data_csv += ','.join(map(str,row))+'\n'
                      wr.writerow(row)
          fp.close()
          self.csvs['ReactionData.csv'] = reaction_data_csv
  
          enzyme_data_csv = ''
          if len(self.SessionName) > 0:
              filename = self.SessionName+'_EnzymeData.csv'
          else:
              filename = 'EnzymeData.csv'
          with open(filename, "w", newline='') as fp:
              wr = csv.writer(fp, dialect='excel')
              IDs = list(self.EnzymeData.Elements.keys())
              enzyme_data_csv += ','.join(['']+list(self.EnzymeData.Elements[IDs[0]].keys()))+'\n'
              wr.writerow([None]+list(self.EnzymeData.Elements[IDs[0]].keys()))
              for i in list(IDs):
                  valuerow = list(self.EnzymeData.Elements[i].values())
                  if deleteZerosRows:
                      if not all(v == 0 for v in valuerow):
                          row = [i]+valuerow
                          enzyme_data_csv += ','.join(map(str,row))+'\n'
                          wr.writerow(row)
                  else:
                      row = [i]+valuerow
                      enzyme_data_csv += ','.join(map(str,row))+'\n'
                      wr.writerow(row)
          fp.close()
          self.csvs['EnzymeData.csv'] = enzyme_data_csv
  
          protein_data_csv = ''
          if len(self.SessionName) > 0:
              filename = self.SessionName+'_ProteinData.csv'
          else:
              filename = 'ProteinData.csv'
          with open(filename, "w", newline='') as fp:
              wr = csv.writer(fp, dialect='excel')
              IDs = list(self.ProteinData.Elements.keys())
              protein_data_csv += ','.join(['']+list(self.ProteinData.Elements[IDs[0]].keys()))+'\n'
              wr.writerow([None]+list(self.ProteinData.Elements[IDs[0]].keys()))
              for i in list(IDs):
                  valuerow = list(self.ProteinData.Elements[i].values())
                  if deleteZerosRows:
                      if not all(v == 0 for v in valuerow):
                          row = [i]+valuerow
                          protein_data_csv += ','.join(map(str,row))+'\n'
                          wr.writerow(row)
                  else:
                      row = [i]+valuerow
                      protein_data_csv += ','.join(map(str,row))+'\n'
                      wr.writerow(row)
          fp.close()
          self.csvs['ProteinData.csv'] = protein_data_csv
  
          proto_data_csv = ''
          if len(self.SessionName) > 0:
              filename = self.SessionName+'_ProtoProteinData.csv'
          else:
              filename = 'ProtoProteinData.csv'
          with open(filename, "w", newline='') as fp:
              wr = csv.writer(fp, dialect='excel')
              IDs = list(self.ProtoProteinData.Elements.keys())
              proto_data_csv += ','.join(['']+list(self.ProtoProteinData.Elements[IDs[0]].keys()))+'\n'
              wr.writerow([None]+list(self.ProtoProteinData.Elements[IDs[0]].keys()))
              for i in list(IDs):
                  valuerow = list(self.ProtoProteinData.Elements[i].values())
                  if deleteZerosRows:
                      if not all(v == 0 for v in valuerow):
                          row = [i]+valuerow
                          proto_data_csv += ','.join(map(str,row))+'\n'
                          wr.writerow(row)
                  else:
                      row = [i]+valuerow
                      proto_data_csv += ','.join(map(str,row))+'\n'
                      wr.writerow(row)
          fp.close()
          self.csvs['ProtoData.csv'] = proto_data_csv
  
          process_data_csv = ''
          if len(self.SessionName) > 0:
              filename = self.SessionName+'_ProcessData.csv'
          else:
              filename = 'ProcessData.csv'
          with open(filename, "w", newline='') as fp:
              wr = csv.writer(fp, dialect='excel')
              IDs = list(self.ProcessData.Elements.keys())
              process_data_csv += ','.join(['']+list(self.ProcessData.Elements[IDs[0]].keys()))+'\n'
              wr.writerow([None]+list(self.ProcessData.Elements[IDs[0]].keys()))
              for i in list(IDs):
                  valuerow = list(self.ProcessData.Elements[i].values())
                  if deleteZerosRows:
                      if not all(v == 0 for v in valuerow):
                          row = [i]+valuerow
                          process_data_csv += ','.join(map(str,row))+'\n'
                          wr.writerow(row)
                  else:
                      row = [i]+valuerow
                      process_data_csv += ','.join(map(str,row))+'\n'
                      wr.writerow(row)
          fp.close()
          self.csvs['ProcessData.csv'] = process_data_csv
  
          metabolite_constraint_csv = ''
          if len(self.SessionName) > 0:
              filename = self.SessionName+'_MetaboliteConstraintData.csv'
          else:
              filename = 'MetaboliteConstraintData.csv'
          with open(filename, "w", newline='') as fp:
              wr = csv.writer(fp, dialect='excel')
              IDs = list(self.MetaboliteConstraintData.Elements.keys())
              metabolite_constraint_csv += ','.join(['']+list(self.MetaboliteConstraintData.Elements[IDs[0]].keys()))+'\n'
              wr.writerow([None]+list(self.MetaboliteConstraintData.Elements[IDs[0]].keys()))
              for i in list(IDs):
                  valuerow = list(self.MetaboliteConstraintData.Elements[i].values())
                  if deleteZerosRows:
                      if not all(v == 0 for v in valuerow):
                          row = [i]+valuerow
                          metabolite_constraint_csv += ','.join(map(str,row))+'\n'
                          wr.writerow(row)
                  else:
                      row = [i]+valuerow
                      metabolite_constraint_csv += ','.join(map(str,row))+'\n'
                      wr.writerow(row)
          fp.close()
          self.csvs['MetaboliteConstraint.csv'] = metabolite_constraint_csv
  
          density_constraint_csv = ''
          if len(self.SessionName) > 0:
              filename = self.SessionName+'_DensityConstraintData.csv'
          else:
              filename = 'DensityConstraintData.csv'
          with open(filename, "w", newline='') as fp:
              wr = csv.writer(fp, dialect='excel')
              IDs = list(self.DensityConstraintData.Elements.keys())
              density_constraint_csv += ','.join(['']+list(self.DensityConstraintData.Elements[IDs[0]].keys()))+'\n'
              wr.writerow([None]+list(self.DensityConstraintData.Elements[IDs[0]].keys()))
              for i in list(IDs):
                  valuerow = list(self.DensityConstraintData.Elements[i].values())
                  if deleteZerosRows:
                      if not all(v == 0 for v in valuerow):
                          row = [i]+valuerow
                          density_constraint_csv += ','.join(map(str,row))+'\n'
                          wr.writerow(row)
                  else:
                      row = [i]+valuerow
                      density_constraint_csv += ','.join(map(str,row))+'\n'
                      wr.writerow(row)
          fp.close()
          self.csvs['DensityConstraint.csv'] = density_constraint_csv
  
          process_constraint_csv = ''
          if len(self.SessionName) > 0:
              filename = self.SessionName+'_ProcessConstraintData.csv'
          else:
              filename = 'ProcessConstraintData.csv'
          with open(filename, "w", newline='') as fp:
              wr = csv.writer(fp, dialect='excel')
              IDs = list(self.ProcessConstraintData.Elements.keys())
              process_constraint_csv += ','.join(['']+list(self.ProcessConstraintData.Elements[IDs[0]].keys()))+'\n'
              wr.writerow([None]+list(self.ProcessConstraintData.Elements[IDs[0]].keys()))
              for i in list(IDs):
                  valuerow = list(self.ProcessConstraintData.Elements[i].values())
                  if deleteZerosRows:
                      if not all(v == 0 for v in valuerow):
                          row = [i]+valuerow
                          process_constraint_csv += ','.join(map(str,row))+'\n'
                          wr.writerow(row)
                  else:
                      row = [i]+valuerow
                      process_constraint_csv += ','.join(map(str,row))+'\n'
                      wr.writerow(row)
          fp.close()
          self.csvs['ProcessConstraint.csv'] = process_constraint_csv
  
          enzyme_constraint_csv = ''
          if len(self.SessionName) > 0:
              filename = self.SessionName+'_EnzymeConstraintData.csv'
          else:
              filename = 'EnzymeConstraintData.csv'
          with open(filename, "w", newline='') as fp:
              wr = csv.writer(fp, dialect='excel')
              IDs = list(self.EnzymeConstraintData.Elements.keys())
              enzyme_constraint_csv += ','.join(['']+list(self.EnzymeConstraintData.Elements[IDs[0]].keys()))+'\n'
              wr.writerow([None]+list(self.EnzymeConstraintData.Elements[IDs[0]].keys()))
              for i in list(IDs):
                  valuerow = list(self.EnzymeConstraintData.Elements[i].values())
                  if deleteZerosRows:
                      if not all(v == 0 for v in valuerow):
                          row = [i]+valuerow
                          enzyme_constraint_csv += ','.join(map(str,row))+'\n'
                          wr.writerow(row)
                  else:
                      row = [i]+valuerow
                      enzyme_constraint_csv += ','.join(map(str,row))+'\n'
                      wr.writerow(row)
          fp.close()
          self.csvs['EnzymeConstraint.csv'] = enzyme_constraint_csv
  
      def getCSVFiles(self):
          return self.csvs
  
      def exportEscherMap(self, etype='fluxes'):
          """
          Exports input file for generation of Escher maps.
  
          https://escher.github.io
  
          If argument type is 'fluxes' the method return an Eschermap for the
          visualisation of reaction-fluxes
          If argument type is 'investment' the method return an Eschermap for the
          visualisation of the amount of amino-acids invested in enzyme machinery
          for reactions.
  
          Parameters
          ----------
          type: str ('fluxes' or 'investment')
          Default: 'fluxes'
          """
  
          if etype is 'fluxes':
              IDs = [id[2:] for id in list(self.uniqueReactionData.Elements.keys())]
              for run in self.uniqueReactionData.Elements[list(self.uniqueReactionData.Elements.keys())[0]]:
                  Values = [rxn[run] for rxn in list(self.uniqueReactionData.Elements.values())]
                  intermediateReactionFluxes = dict(zip(IDs, Values))
                  ReactionFluxes = {id: val for id,
                                    val in intermediateReactionFluxes.items() if val != 0.}
                  if len(self.SessionName) > 0:
                      filename = self.SessionName+'_RBA_Eschermap_fluxes_'+run+'.json'
                  else:
                      filename = 'RBA_Eschermap_fluxes_'+run+'.json'
                  self.eschermap = json.dumps(ReactionFluxes, indent=4)                    
                  #with open(filename, 'w') as fout:
                  #    fout.write(json.dumps(ReactionFluxes, indent=4))
          if etype is 'investment':
              IDs = list(self.uniqueReactionData.Elements.keys())
              for run in self.uniqueReactionData.Elements[list(self.uniqueReactionData.Elements.keys())[0]]:
                  Fluxes = [rxn[run] for rxn in list(self.uniqueReactionData.Elements.values())]
                  Intermediate = zip(IDs, Fluxes)
                  RxnsToTest = [i[0] for i in Intermediate if i[1] != 0.]
                  Values = [determineInvestment(self, rxn, run) for rxn in RxnsToTest]
                  ReactionInvestments = {id[2:]: val for id,
                                         val in dict(zip(RxnsToTest, Values)).items()}
                  if len(self.SessionName) > 0:
                      filename = self.SessionName+'_RBA_Eschermap_investment_'+run+'.json'
                  else:
                      filename = 'RBA_Eschermap_investment_'+run+'.json'
                  self.eschermap = json.dumps(ReactionInvestments, indent=4)
                  #with open(filename, 'w') as fout:
                  #    fout.write(json.dumps(ReactionInvestments, indent=4))
      
      def getEscherMap(self):
          return self.eschermap
  
      def exportProteoMap(self, etype='proto'):
          """
          Exports input file for the generation of Proteo maps from
          simulation data.
  
          https://www.proteomaps.net
          """
          if etype == 'isoforms':
              IDs = list(self.ProteinData.Elements.keys())
              for run in self.ProteinData.Elements[list(self.ProteinData.Elements.keys())[0]]:
                  Values = [protein[run] for protein in list(self.ProteinData.Elements.values())]
                  intermediateProteinLevels = dict(zip(IDs, Values))
                  ProteinLevels = {id: val for id,
                                   val in intermediateProteinLevels.items() if val != 0.}
                  if len(self.SessionName) > 0:
                      filename = self.SessionName+'_RBA_Proteomap_'+run+'.tsv'
                  else:
                      filename = 'RBA_Proteomap_'+run+'.tsv'
                  self.proteomap = '\n'.join(['{}\t{}'.format(p, l) for p, l in ProteinLevels.items()]) 
          if etype == 'proto':
              IDs = list(self.ProtoProteinData.Elements.keys())
              for run in self.ProtoProteinData.Elements[list(self.ProtoProteinData.Elements.keys())[0]]:
                  Values = [protein[run] for protein in list(self.ProtoProteinData.Elements.values())]
                  intermediateProteinLevels = dict(zip(IDs, Values))
                  ProteinLevels = {id: val for id,
                                   val in intermediateProteinLevels.items() if val != 0.}
                  if len(self.SessionName) > 0:
                      filename = self.SessionName+'_RBA_Proteomap_'+run+'.tsv'
                  else:
                      filename = 'RBA_Proteomap_'+run+'.tsv'
                  self.proteomap = '\n'.join(['{}\t{}'.format(p, l) for p, l in ProteinLevels.items()])
  
      def getProteoMap(self):
          return self.proteomap
  
  def htmlStyle(structOriginal):
      struct = copy.deepcopy(structOriginal)
      for i in list(struct.ReactionData.Elements.keys()):
          struct.ReactionData.Elements['ID_' + i + '_Data'] = struct.ReactionData.Elements.pop(i)
      for i in list(struct.EnzymeData.Elements.keys()):
          struct.EnzymeData.Elements['ID_' + i + '_Data'] = struct.EnzymeData.Elements.pop(i)
      for i in list(struct.ProcessData.Elements.keys()):
          struct.ProcessData.Elements['ID_' + i + '_Data'] = struct.ProcessData.Elements.pop(i)
      for i in list(struct.ProteinData.Elements.keys()):
          struct.ProteinData.Elements['ID_' + i + '_Data'] = struct.ProteinData.Elements.pop(i)
      for i in list(struct.MetaboliteConstraintData.Elements.keys()):
          struct.MetaboliteConstraintData.Elements['ID_' + i +
                                                   '_Data'] = struct.MetaboliteConstraintData.Elements.pop(i)
      for i in list(struct.DensityConstraintData.Elements.keys()):
          struct.DensityConstraintData.Elements['ID_' + i +
                                                '_Data'] = struct.DensityConstraintData.Elements.pop(i)
      for i in list(struct.EnzymeConstraintData.Elements.keys()):
          struct.EnzymeConstraintData.Elements['ID_' + i +
                                               '_Data'] = struct.EnzymeConstraintData.Elements.pop(i)
      for i in list(struct.ProcessConstraintData.Elements.keys()):
          struct.ProcessConstraintData.Elements['ID_' + i +
                                                '_Data'] = struct.ProcessConstraintData.Elements.pop(i)
      Block = {'RunInfo': struct.GeneralRunInfo.JSONize(),
               'ReactionData': struct.ReactionData.JSONize(),
               'ProteinData': struct.ProteinData.JSONize(),
               'EnzymeData': struct.EnzymeData.JSONize(),
               'ProcessData': struct.ProcessData.JSONize(),
               'MetaboliteConstraintData': struct.MetaboliteConstraintData.JSONize(),
               'DensityConstraintData': struct.DensityConstraintData.JSONize(),
               'EnzymeConstraintData': struct.EnzymeConstraintData.JSONize(),
               'ProcessConstraintData': struct.ProcessConstraintData.JSONize()}
      return({'RBA_ModelData': {'SimulationData': Block}})
  
  
  def htmlStyleAddingCol(structOriginal):
      struct = copy.deepcopy(structOriginal)
      for i in list(struct.ReactionData.Elements.keys()):
          count = 0
          for j in list(struct.ReactionData.Elements[i].keys()):
              if j is not 'correspondingElement':
                  count += 1
                  struct.ReactionData.Elements[i]['C' +
                                                  str(count)+'___'+j] = struct.ReactionData.Elements[i].pop(j)
          struct.ReactionData.Elements['ID_' + i + '_Data'] = struct.ReactionData.Elements.pop(i)
      for i in list(struct.EnzymeData.Elements.keys()):
          count = 0
          for j in list(struct.EnzymeData.Elements[i].keys()):
              if j is not 'correspondingElement':
                  count += 1
                  struct.EnzymeData.Elements[i]['C' +
                                                str(count)+'___'+j] = struct.EnzymeData.Elements[i].pop(j)
          struct.EnzymeData.Elements['ID_' + i + '_Data'] = struct.EnzymeData.Elements.pop(i)
      for i in list(struct.ProcessData.Elements.keys()):
          count = 0
          for j in list(struct.ProcessData.Elements[i].keys()):
              if j is not 'correspondingElement':
                  count += 1
                  struct.ProcessData.Elements[i]['C' +
                                                 str(count)+'___'+j] = struct.ProcessData.Elements[i].pop(j)
          struct.ProcessData.Elements['ID_' + i + '_Data'] = struct.ProcessData.Elements.pop(i)
      for i in list(struct.ProteinData.Elements.keys()):
          count = 0
          for j in list(struct.ProteinData.Elements[i].keys()):
              if j is not 'correspondingElement':
                  count += 1
                  struct.ProteinData.Elements[i]['C' +
                                                 str(count)+'___'+j] = struct.ProteinData.Elements[i].pop(j)
          struct.ProteinData.Elements['ID_' + i + '_Data'] = struct.ProteinData.Elements.pop(i)
      for i in list(struct.MetaboliteConstraintData.Elements.keys()):
          count = 0
          for j in list(struct.MetaboliteConstraintData.Elements[i].keys()):
              if j is not 'correspondingElement':
                  count += 1
                  struct.MetaboliteConstraintData.Elements[i]['C'+str(
                      count)+'___'+j] = struct.MetaboliteConstraintData.Elements[i].pop(j)
          struct.MetaboliteConstraintData.Elements['ID_' + i +
                                                   '_Data'] = struct.MetaboliteConstraintData.Elements.pop(i)
      for i in list(struct.DensityConstraintData.Elements.keys()):
          count = 0
          for j in list(struct.DensityConstraintData.Elements[i].keys()):
              if j is not 'correspondingElement':
                  count += 1
                  struct.DensityConstraintData.Elements[i]['C' +
                                                           str(count)+'___'+j] = struct.DensityConstraintData.Elements[i].pop(j)
          struct.DensityConstraintData.Elements['ID_' + i +
                                                '_Data'] = struct.DensityConstraintData.Elements.pop(i)
      for i in list(struct.EnzymeConstraintData.Elements.keys()):
          count = 0
          for j in list(struct.EnzymeConstraintData.Elements[i].keys()):
              if j is not 'correspondingElement':
                  count += 1
                  struct.EnzymeConstraintData.Elements[i]['C' +
                                                          str(count)+'___'+j] = struct.EnzymeConstraintData.Elements[i].pop(j)
          struct.EnzymeConstraintData.Elements['ID_' + i +
                                               '_Data'] = struct.EnzymeConstraintData.Elements.pop(i)
      for i in list(struct.ProcessConstraintData.Elements.keys()):
          count = 0
          for j in list(struct.ProcessConstraintData.Elements[i].keys()):
              if j is not 'correspondingElement':
                  count += 1
                  struct.ProcessConstraintData.Elements[i]['C' +
                                                           str(count)+'___'+j] = struct.ProcessConstraintData.Elements[i].pop(j)
          struct.ProcessConstraintData.Elements['ID_' + i +
                                                '_Data'] = struct.ProcessConstraintData.Elements.pop(i)
      Block = {'RunInfo': struct.GeneralRunInfo.JSONize(),
               'ReactionData': struct.ReactionData.JSONize(),
               'ProteinData': struct.ProteinData.JSONize(),
               'EnzymeData': struct.EnzymeData.JSONize(),
               'ProcessData': struct.ProcessData.JSONize(),
               'MetaboliteConstraintData': struct.MetaboliteConstraintData.JSONize(),
               'DensityConstraintData': struct.DensityConstraintData.JSONize(),
               'EnzymeConstraintData': struct.EnzymeConstraintData.JSONize(),
               'ProcessConstraintData': struct.ProcessConstraintData.JSONize()}
      return({'RBA_ModelData': {'SimulationData': Block}})
  
  
  def htmlStyleReplacingCol(structOriginal):
      struct = copy.deepcopy(structOriginal)
      for i in list(struct.ReactionData.Elements.keys()):
          count = 0
          for j in list(struct.ReactionData.Elements[i].keys()):
              if j is not 'correspondingElement':
                  count += 1
                  struct.ReactionData.Elements[i]['C' +
                                                  str(count)] = struct.ReactionData.Elements[i].pop(j)
          struct.ReactionData.Elements['ID_' + i + '_Data'] = struct.ReactionData.Elements.pop(i)
      for i in list(struct.EnzymeData.Elements.keys()):
          count = 0
          for j in list(struct.EnzymeData.Elements[i].keys()):
              if j is not 'correspondingElement':
                  count += 1
                  struct.EnzymeData.Elements[i]['C'+str(count)] = struct.EnzymeData.Elements[i].pop(j)
          struct.EnzymeData.Elements['ID_' + i + '_Data'] = struct.EnzymeData.Elements.pop(i)
      for i in list(struct.ProcessData.Elements.keys()):
          count = 0
          for j in list(struct.ProcessData.Elements[i].keys()):
              if j is not 'correspondingElement':
                  count += 1
                  struct.ProcessData.Elements[i]['C' +
                                                 str(count)] = struct.ProcessData.Elements[i].pop(j)
          struct.ProcessData.Elements['ID_' + i + '_Data'] = struct.ProcessData.Elements.pop(i)
      for i in list(struct.ProteinData.Elements.keys()):
          count = 0
          for j in list(struct.ProteinData.Elements[i].keys()):
              if j is not 'correspondingElement':
                  count += 1
                  struct.ProteinData.Elements[i]['C' +
                                                 str(count)] = struct.ProteinData.Elements[i].pop(j)
          struct.ProteinData.Elements['ID_' + i + '_Data'] = struct.ProteinData.Elements.pop(i)
      for i in list(struct.MetaboliteConstraintData.Elements.keys()):
          count = 0
          for j in list(struct.MetaboliteConstraintData.Elements[i].keys()):
              if j is not 'correspondingElement':
                  count += 1
                  struct.MetaboliteConstraintData.Elements[i]['C' +
                                                              str(count)] = struct.MetaboliteConstraintData.Elements[i].pop(j)
          struct.MetaboliteConstraintData.Elements['ID_' + i +
                                                   '_Data'] = struct.MetaboliteConstraintData.Elements.pop(i)
      for i in list(struct.DensityConstraintData.Elements.keys()):
          count = 0
          for j in list(struct.DensityConstraintData.Elements[i].keys()):
              if j is not 'correspondingElement':
                  count += 1
                  struct.DensityConstraintData.Elements[i]['C' +
                                                           str(count)] = struct.DensityConstraintData.Elements[i].pop(j)
          struct.DensityConstraintData.Elements['ID_' + i +
                                                '_Data'] = struct.DensityConstraintData.Elements.pop(i)
      for i in list(struct.EnzymeConstraintData.Elements.keys()):
          count = 0
          for j in list(struct.EnzymeConstraintData.Elements[i].keys()):
              if j is not 'correspondingElement':
                  count += 1
                  struct.EnzymeConstraintData.Elements[i]['C' +
                                                          str(count)] = struct.EnzymeConstraintData.Elements[i].pop(j)
          struct.EnzymeConstraintData.Elements['ID_' + i +
                                               '_Data'] = struct.EnzymeConstraintData.Elements.pop(i)
      for i in list(struct.ProcessConstraintData.Elements.keys()):
          count = 0
          for j in list(struct.ProcessConstraintData.Elements[i].keys()):
              if j is not 'correspondingElement':
                  count += 1
                  struct.ProcessConstraintData.Elements[i]['C' +
                                                           str(count)] = struct.ProcessConstraintData.Elements[i].pop(j)
          struct.ProcessConstraintData.Elements['ID_' + i +
                                                '_Data'] = struct.ProcessConstraintData.Elements.pop(i)
      Block = {'RunInfo': struct.GeneralRunInfo.JSONize(),
               'ReactionData': struct.ReactionData.JSONize(),
               'ProteinData': struct.ProteinData.JSONize(),
               'EnzymeData': struct.EnzymeData.JSONize(),
               'ProcessData': struct.ProcessData.JSONize(),
               'MetaboliteConstraintData': struct.MetaboliteConstraintData.JSONize(),
               'DensityConstraintData': struct.DensityConstraintData.JSONize(),
               'EnzymeConstraintData': struct.EnzymeConstraintData.JSONize(),
               'ProcessConstraintData': struct.ProcessConstraintData.JSONize()}
      return({'RBA_ModelData': {'SimulationData': Block}})
  
  
  def determineInvestment(SimData, rxn, run):
      investment = 0
      isoReactions = SimData.StructuralInformation.ReactionInfo.Elements[rxn]['Twins']+[rxn]
      enzymesToCheck = [SimData.StructuralInformation.ReactionInfo.Elements[r]['Enzyme'] for r in isoReactions if len(
          SimData.StructuralInformation.ReactionInfo.Elements[r]['Enzyme']) > 0]
      for enzy in enzymesToCheck:
          prots = SimData.StructuralInformation.EnzymeInfo.Elements[enzy]['Subunits']
          enzymeCost = 0
          for pr in list(prots.items()):
              SF = int(pr[1])
              AAnum = SimData.StructuralInformation.ProteinInfo.Elements[pr[0]]['AAnumber']
              if numpy.isnan(AAnum):
                  continue
              enzymeCost += SF*int(AAnum)
          investment += enzymeCost*SimData.EnzymeData.Elements[enzy][run]
      return(investment)
  