Salome HOME
Example of a python component from Salome tutorial
[samples/atomgen.git] / src / ATOMGEN / ATOMGEN.py
1 #  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
2 #
3 #  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 #  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 #
6 #  This library is free software; you can redistribute it and/or
7 #  modify it under the terms of the GNU Lesser General Public
8 #  License as published by the Free Software Foundation; either
9 #  version 2.1 of the License.
10 #
11 #  This library is distributed in the hope that it will be useful,
12 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 #  Lesser General Public License for more details.
15 #
16 #  You should have received a copy of the GNU Lesser General Public
17 #  License along with this library; if not, write to the Free Software
18 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 #
20 #  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
21
22 import ATOMGEN_ORB
23 import ATOMGEN_ORB__POA
24 import SALOME_ComponentPy
25 import SALOME_DriverPy
26 import SALOMEDS
27
28 #--- init ORB ---
29 from omniORB import CORBA
30 myORB = CORBA.ORB_init([''], CORBA.ORB_ID)
31
32 def ObjectToString(object):
33     return myORB.object_to_string(object)
34
35 def StringToObject(string):
36     return myORB.string_to_object(string)
37
38 #--- init POA ---
39 from omniORB import PortableServer
40 myPOA = myORB.resolve_initial_references("RootPOA");
41
42 def ObjectToServant(object):
43     return myPOA.reference_to_servant(object)
44
45 __entry2IOR__ = {}
46
47 #--- Engine implementation ---
48 class ATOMGEN( ATOMGEN_ORB__POA.ATOMGEN_Gen,
49                SALOME_ComponentPy.SALOME_ComponentPy_i,
50                SALOME_DriverPy.SALOME_DriverPy_i ):
51     """
52     ATOMGEN component engine
53     """
54     def __init__ ( self, orb, poa, contID, containerName, instanceName,
55                    interfaceName ):
56         """
57         Constructor
58         """
59         SALOME_ComponentPy.SALOME_ComponentPy_i.__init__( self, orb, poa,
60                                                           contID, containerName,
61                                                           instanceName, interfaceName, 0 )
62         SALOME_DriverPy.SALOME_DriverPy_i.__init__( self, interfaceName )
63         
64         self._naming_service = SALOME_ComponentPy.SALOME_NamingServicePy_i( self._orb )
65         self.study = None
66         self.studyData = {}
67         pass
68
69     def getData( self, studyID ):
70         """
71         Gets study data
72         """
73         if self.studyData.has_key( studyID ):
74             l = []
75             for m in self.studyData[ studyID ]:
76                 l.append( m._this() )
77             return l
78         print "ATOMGEN: getData() failed because studyID ", str( studyID ), " was not found"
79         return []
80
81     def Save( self, component, URL, isMultiFile ):
82         """
83         Saves data.
84         Nothing to do here because in our case all data
85         are stored in the SALOMEDS attributes.
86         """
87         return ""
88
89     def Load( self, component, stream, URL, isMultiFile ):
90         """
91         Loads data
92         """
93         global __entry2IOR__
94         __entry2IOR__.clear()
95         import StringIO, pickle
96         study = component.GetStudy()
97         self.setCurrentStudy( study )
98         iter = study.NewChildIterator(component)
99         data = []
100         while iter.More():
101             sobject = iter.Value()
102             iter.Next()
103             found, attr = sobject.FindAttribute("AttributeName")
104             if not found: continue
105             from ATOMGEN_Data import Molecule, Atom
106             mol = Molecule(attr.Value())
107             __entry2IOR__[sobject.GetID()] = ObjectToString(mol._this())
108             iter1 = study.NewChildIterator(sobject)
109             while iter1.More():
110                 sobject1 = iter1.Value()
111                 iter1.Next()
112                 found, attr = sobject1.FindAttribute("AttributeName")
113                 if not found: continue
114                 name = attr.Value()
115                 x = y = z = None
116                 iter2 = study.NewChildIterator(sobject1)
117                 while iter2.More():
118                     sobject2 = iter2.Value()
119                     iter2.Next()
120                     found, attr1 = sobject2.FindAttribute("AttributeName")
121                     if not found: continue
122                     found, attr2 = sobject2.FindAttribute("AttributeReal")
123                     if not found: continue
124                     if attr1.Value() == "x": x = attr2.Value()
125                     if attr1.Value() == "y": y = attr2.Value()
126                     if attr1.Value() == "z": z = attr2.Value()
127                 if None not in [x, y, z]:
128                     atom = Atom(name, x, y, z)
129                     mol.addAtom(atom)
130                     __entry2IOR__[sobject1.GetID()] = ObjectToString(atom._this())
131                 pass
132             data.append(mol)
133         self.appendData( data, False )
134         return 1
135
136     def IORToLocalPersistentID(self, sobject, IOR, isMultiFile, isASCII):
137         """
138         Gets persistent ID for the CORBA object.
139         It's enough to use study entry.
140         """
141         return sobject.GetID()
142
143     def LocalPersistentIDToIOR(self, sobject, persistentID, isMultiFile, isASCII):
144         "Converts persistent ID of the object to its IOR."
145         global __entry2IOR__
146         if __entry2IOR__.has_key(persistentID):
147             return __entry2IOR__[persistentID]
148         return ""
149
150     def Close( self, component ):
151         """
152         Called when study is closed
153         """
154         study = component.GetStudy()
155         if study and self.studyData.has_key( study._get_StudyId() ):
156             del self.studyData[ study._get_StudyId() ]
157         if study == self.study:
158             self.study = None
159         pass
160
161     def CanPublishInStudy( self, IOR ):
162         """
163         Returns True if the object can be published.
164         Nothing to do here. Usually this method should perform
165         check for the object type.
166         """
167         return True
168
169     def PublishInStudy( self, study, sobject, object, name ):
170         """
171         Publishes the object in the study.
172         """
173         if study and object and object._narrow(ATOMGEN_ORB.Molecule):
174             builder = study.NewBuilder()
175             builder.NewCommand()
176             # get or create component object
177             father = study.FindComponent(self._ComponentDataType)
178             if father is None:
179                 builder
180                 father = builder.NewComponent(self._ComponentDataType)
181                 attr = builder.FindOrCreateAttribute(father, "AttributeName")
182                 attr.SetValue(self._ComponentDataType)
183                 builder.DefineComponentInstance(father, self._this())
184                 pass
185             # publish molecule
186             sobject = builder.NewObject(father)
187             attr = builder.FindOrCreateAttribute(sobject, "AttributeName")
188             if not name:
189                 name = object.getName()
190             attr.SetValue(name)
191             attr = builder.FindOrCreateAttribute(sobject, "AttributeIOR")
192             attr.SetValue(ObjectToString(object))
193             # publish atoms
194             for i in range(object.getNbAtoms()):
195                 atom = object.getAtom( i )
196                 sobject1 = builder.NewObject(sobject)
197                 attr = builder.FindOrCreateAttribute(sobject1, "AttributeName")
198                 attr.SetValue(atom.getName())
199                 attr = builder.FindOrCreateAttribute(sobject1, "AttributeIOR")
200                 attr.SetValue(ObjectToString(atom))
201                 sobject2 = builder.NewObject(sobject1)
202                 attr = builder.FindOrCreateAttribute(sobject2, "AttributeName")
203                 attr.SetValue("x")
204                 attr = builder.FindOrCreateAttribute(sobject2, "AttributeReal")
205                 attr.SetValue(atom.getX())
206                 sobject2 = builder.NewObject(sobject1)
207                 attr = builder.FindOrCreateAttribute(sobject2, "AttributeName")
208                 attr.SetValue("y")
209                 attr = builder.FindOrCreateAttribute(sobject2, "AttributeReal")
210                 attr.SetValue(atom.getY())
211                 sobject2 = builder.NewObject(sobject1)
212                 attr = builder.FindOrCreateAttribute(sobject2, "AttributeName")
213                 attr.SetValue("z")
214                 attr = builder.FindOrCreateAttribute(sobject2, "AttributeReal")
215                 attr.SetValue(atom.getZ())
216             builder.CommitCommand()
217             return sobject
218         return None
219
220     def setCurrentStudy( self, study ):
221         """
222         Sets the active study
223         """
224         self.study = study
225         if self.study and not self.getData( self.study._get_StudyId() ):
226             studyID = self.study._get_StudyId()
227             self.studyData[ studyID ] = []
228             print "ATOMGEN: init new array for studyID ", str( studyID ) 
229         pass
230
231     def importXmlFile( self, fileName ):
232         """
233         Imports atomic data from external XML file
234         and publishes the data in the active study
235         """
236         if self.study:
237             # import file
238             from ATOMGEN_XmlParser import readXmlFile
239             new_data = readXmlFile( fileName )
240             self.appendData( new_data )
241             return True
242         return False
243
244     def exportXmlFile( self, fileName ):
245         """
246         Exports atomic data from the active study to
247         the external XML file
248         """
249         if self.study:
250             from ATOMGEN_XmlParser import writeXmlFile
251             data = self.getData( self.study._get_StudyId() )
252             writeXmlFile( fileName, data )
253             return True
254         return False
255
256     def processData( self, data ):
257         """
258         Perform some specific action on the atomic data
259         """
260         if not self.study: return False
261         nb_steps = 5
262         new_data = []
263         dx = 10.0
264         dy = 5.0
265         dz = 3.0
266         for i in range( nb_steps ):
267             for mol in data:
268                 new_mol = self._translateMolecule( mol, i, dx * (i+1), dy * (i+1), dz * (i+1) )                
269                 new_data.append( new_mol )
270         self.appendData( new_data )
271         return True
272
273     def appendData( self, new_data, publish = True ):
274         """
275         Add new molecules to data published under current study
276         """
277         # activate servants
278         if not self.study:
279             return False
280         for mol in new_data:
281             for i in range(mol.getNbAtoms()):
282                 mol.atoms[ i ]._this()
283             mol_servant = mol._this()
284             if publish :
285                 self.PublishInStudy(self.study, None, mol_servant, mol_servant.getName())
286         # store data
287         studyID = self.study._get_StudyId()
288         if self.studyData.has_key( studyID ):
289             data = self.studyData[ studyID ]
290             data += new_data
291             self.studyData[ studyID ] = data
292             return True
293         print "ATOMGEN: could not append new data because studyID ", str( studyID ), " was not found"
294         return False
295
296     def _translateMolecule( self, mol, i, dx, dy, dz ):
297         """
298         Translates atomic molecule along x, y, z axis
299         by given distances dx, dy, dz
300         Returns translated molecule
301         """
302         mol = ObjectToServant( mol )
303         from ATOMGEN_Data import Molecule, Atom
304         new_mol = Molecule( mol.name + "_translated_" + str( i ) )
305         for atom in mol.atoms:
306             new_mol.addAtom( Atom( atom.name, atom.x + dx, atom.y + dy, atom.z + dz ) )
307         return new_mol
308