libSBML Python API  5.18.0
setIdFromNames.py

Program that renames all SIds that also have names specified. The new identifiers will be derived from the name, with all invalid characters removed.

1 #!/usr/bin/env python
2 ##
3 ## @file setIdFromNames.py
4 ## @brief Utility program, renaming all SIds that also has
5 ## names specified. The new id will be derived from
6 ## the name, with all invalid characters removed.
7 ##
8 ## @author Frank T. Bergmann
9 ##
10 ##
11 ## <!--------------------------------------------------------------------------
12 ## This sample program is distributed under a different license than the rest
13 ## of libSBML. This program uses the open-source MIT license, as follows:
14 ##
15 ## Copyright (c) 2013-2018 by the California Institute of Technology
16 ## (California, USA), the European Bioinformatics Institute (EMBL-EBI, UK)
17 ## and the University of Heidelberg (Germany), with support from the National
18 ## Institutes of Health (USA) under grant R01GM070923. All rights reserved.
19 ##
20 ## Permission is hereby granted, free of charge, to any person obtaining a
21 ## copy of this software and associated documentation files (the "Software"),
22 ## to deal in the Software without restriction, including without limitation
23 ## the rights to use, copy, modify, merge, publish, distribute, sublicense,
24 ## and/or sell copies of the Software, and to permit persons to whom the
25 ## Software is furnished to do so, subject to the following conditions:
26 ##
27 ## The above copyright notice and this permission notice shall be included in
28 ## all copies or substantial portions of the Software.
29 ##
30 ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31 ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
33 ## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34 ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
35 ## FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
36 ## DEALINGS IN THE SOFTWARE.
37 ##
38 ## Neither the name of the California Institute of Technology (Caltech), nor
39 ## of the European Bioinformatics Institute (EMBL-EBI), nor of the University
40 ## of Heidelberg, nor the names of any contributors, may be used to endorse
41 ## or promote products derived from this software without specific prior
42 ## written permission.
43 ## ------------------------------------------------------------------------ -->
44 ##
45 ##
46 
47 import sys
48 import os.path
49 import time
50 import libsbml
51 
52 # This class implements an identifier transformer, that means it can be used
53 # to rename all sbase elements.
54 class SetIdFromNames(libsbml.IdentifierTransformer):
55  def __init__(self, ids):
56  # call the constructor of the base class
57  libsbml.IdentifierTransformer.__init__(self)
58  # remember existing ids ...
59  self.existingIds = ids
60 
61  # The function actually doing the transforming. This function is called
62  # once for each SBase element in the model.
63  def transform(self, element):
64  # return in case we don't have a valid element
65  if element is None or element.getTypeCode() == libsbml.SBML_LOCAL_PARAMETER:
66  return libsbml.LIBSBML_OPERATION_SUCCESS
67 
68  # or if there is nothing to do
69  if element.isSetName() == False or element.getId() == element.getName():
70  return libsbml.LIBSBML_OPERATION_SUCCESS
71 
72  # find the new id
73  newId = self.getValidIdForName(element.getName())
74 
75  # set it
76  element.setId(newId)
77 
78  # remember it
79  self.existingIds.append(newId)
80 
81  return libsbml.LIBSBML_OPERATION_SUCCESS
82 
83  def nameToSbmlId(self, name):
84  IdStream = []
85  count = 0
86  end = len(name)
87 
88  if '0' <= name[count] and name[count] <= '9':
89  IdStream.append('_')
90  for count in range (0, end):
91  if (('0' <= name[count] and name[count] <= '9') or
92  ('a' <= name[count] and name[count] <= 'z') or
93  ('A' <= name[count] and name[count] <= 'Z')):
94  IdStream.append(name[count])
95  else:
96  IdStream.append('_')
97  Id = ''.join(IdStream)
98  if Id[len(Id) - 1] != '_':
99  return Id
100 
101  return Id[:-1]
102  #
103  # Generates the id out of the name, and ensures it is unique.
104  # It does so by appending numbers to the original name.
105  #
106  def getValidIdForName(self, name):
107  baseString = self.nameToSbmlId(name)
108  id = baseString
109  count = 1
110  while self.existingIds.count(id) != 0:
111  id = "{0}_{1}".format(baseString, count)
112  count += 1
113  return id
114 
115 
116 #
117 # Returns a list of all ids from the given list of elements
118 #
119 def getAllIds(allElements):
120  result = []
121  if allElements is None or allElements.getSize() == 0:
122  return result
123 
124  for i in range (0, allElements.getSize()):
125  current = allElements.get(i)
126  if current.isSetId() and current.getTypeCode() != libsbml.SBML_LOCAL_PARAMETER:
127  result.append(current.getId())
128  return result
129 
130 
131 def main (args):
132  """Usage: setIdFromNames filename output
133  """
134  if len(args) != 3:
135  print(main.__doc__)
136  sys.exit(1)
137 
138  filename = args[1]
139  output = args[2]
140 
141  # read the document
142  start = time.time() * 1000
143  document = libsbml.readSBMLFromFile(filename)
144  stop = time.time() * 1000
145 
146  print ("")
147  print (" filename: {0}".format( filename))
148  print (" read time (ms): {0}".format( stop - start))
149 
150  # stop in case of serious errors
151  errors = document.getNumErrors(libsbml.LIBSBML_SEV_ERROR)
152  if errors > 0:
153  print (" error(s): {0}".format(errors))
154  document.printErrors()
155  sys.exit (errors)
156 
157  # get a list of all elements, as we will need to know all identifiers
158  # so that we don't create duplicates.
159  allElements = document.getListOfAllElements()
160 
161  # get a list of all ids
162  allIds = getAllIds(allElements)
163 
164  # create the transformer with the ids
165  trans = SetIdFromNames(allIds)
166 
167  # rename the identifiers (using the elements we already gathered before)
168  start = time.time() * 1000
169  document.getModel().renameIDs(allElements, trans)
170  stop = time.time() * 1000
171  print (" rename time (ms): {0}".format(stop - start))
172 
173  # write to file
174  start = time.time() * 1000
175  libsbml.writeSBMLToFile(document, output)
176  stop = time.time() * 1000
177  print (" write time (ms): {0}".format(stop - start))
178  print ("")
179 
180  # if we got here all went well ...
181 
182 if __name__ == '__main__':
183  main(sys.argv)