1 # -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2011-2015 CEA/DEN, EDF R&D
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License, or (at your option) any later version.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 # Author : Guillaume Boulant (EDF)
26 def newFieldProxy(fieldHandlerId):
28 This creates a new FieldProxy wrapping the field whose
29 fieldHandlerId is passed in argument. The function requests the
30 xmedDataManager to get the fieldHandler from its id.
32 fieldHandler = xmed.dataManager.getFieldHandler(fieldHandlerId)
33 return FieldProxy(fieldHandler)
35 # This define the map between attributes of a FieldProxy and those of
36 # the associated FieldHandler
37 PROXY_ATTRIBUTES_MAP = {"id":None,
43 "iteration":"iteration",
49 This object is a proxy to manipulate a remote MEDCoupling field
50 from within the SALOME python interpreter. Remote means that the
51 MEDCoupling field is in the SALOME container and not in the
52 client. See UserGuide class for detailed documentation of what can
53 be done with a field proxy.
55 def __init__( self, fieldHandler ):
57 This defines the wrapping on the field specified by its
60 self.__fieldHandler = fieldHandler
61 self.__restriction = None
64 def __getattr__(self, name ):
66 This method realizes the read proxy pattern toward the field
69 # WRN: Note that the modification of this function can lead to
70 # coercion problem. Modify this function with extrem care.
71 return getattr( self.__fieldHandler, name )
73 def __setattr__(self, name, value):
75 This method realizes the write proxy pattern toward the field
76 handler. Only some attributes are writable. The list is
77 specified in the PROXY_ATTRIBUTES_MAP table.
79 if name in PROXY_ATTRIBUTES_MAP.keys():
80 if PROXY_ATTRIBUTES_MAP[name] is not None:
81 xmed.wrn("The modification of this attribute can't be done that way")
82 msg="Use f.update(%s=\"%s\") instead to ensure synchronisation of data."
83 xmed.inf(msg%(PROXY_ATTRIBUTES_MAP[name],value))
85 xmed.err("The modification of the attribute %s is not possible"%name)
87 self.__dict__[name] = value
91 Return a string containing a printable representation of this
92 object (what is displayed when typing the variable name and
95 # We need first to update the handler because some data can
96 # have changed (the meshid for example in case of change of
98 # __GBO__ : TODO check the performance
99 self.__fieldHandler = xmed.dataManager.getFieldHandler(self.id)
100 text = "field name (id)\t = %s (%s)\n"%(self.fieldname, self.id)
101 text+= "mesh name (id) \t = %s (%s)\n"%(self.meshname,self.meshid)
102 text+= "discretization \t = %s\n"%xmed.typeOfFieldLabel(self.type)
103 text+= "(iter, order) \t = (%s,%s)\n"%(str(self.iteration),str(self.order))
104 text+= "data source \t = %s"%self.source
109 This is what is displayed when you type 'print myField'. Note
110 that this function prints the values of the field and then you
111 must be aware that a huge amount of data could be
112 displayed. Moreover, it means that this operation triggers the
113 loading of the associated MEDCouplingFied data in the SALOME
116 text = xmed.dataManager.getFieldRepresentation(self.id)
119 def __add__(self, operande):
121 This makes the addition of two fields or the addition of a
122 scalar to a field. It depends weither the operande is a
123 FieldProxy or a simple scalar numerical value.
125 # The xmed calculator could raise exceptions coming from
126 # MEDCoupling. Note that the fieldproxy instances are used
127 # from within the python console, and for ergonomic reason, we
128 # choose to not raise the possible exceptions to the console
129 # by a clear message. Keep this in mind for unit test. You
130 # have to test the return value, which should not be
131 # null. This principle is applyed for all operations.
133 if isinstance(operande, FieldProxy):
134 # The operande is an other field
135 xmed.inf("Addition of %s and %s"%(self.fieldname, operande.fieldname))
136 rfieldHandler = xmed.calculator.add(self.__fieldHandler, operande.__fieldHandler)
138 # The operande is a scalar numerical value that must be
139 # considered as an offset in a linear transformation
142 xmed.inf("Application of the offset %s to %s" % (offset, self.fieldname))
143 rfieldHandler = xmed.calculator.lin(self.__fieldHandler, factor, offset)
144 except SALOME.SALOME_Exception, ex:
145 xmed.err(ex.details.text)
148 return FieldProxy(rfieldHandler)
150 def __radd__(self, operande):
152 The user typed 'operande+self', we replace by 'self+operande'
153 to automatically activate the __add__ method of fieldpoxy.
157 def __iadd__(self, operande):
159 These methods implements the augmented arithmetic assignments (+=)
161 xmed.wrn("NOT IMPLEMENTED YET")
163 def __sub__(self,operande):
165 This makes the substraction of two fields or the substraction
166 of a scalar to a field. It depends weither the operande is a
167 FieldProxy or a simple scalar numerical value.
170 if isinstance(operande, FieldProxy):
171 # The operande is an other field
172 xmed.inf("Substraction of %s by %s"%(self.fieldname, operande.fieldname))
173 rfieldHandler = xmed.calculator.sub(self.__fieldHandler, operande.__fieldHandler)
175 # The operande is a scalar numerical value that must be
176 # considered as an offset in a linear transformation
179 xmed.inf("Application of the offset %s to %s" % (offset, self.fieldname))
180 rfieldHandler = xmed.calculator.lin(self.__fieldHandler, factor, offset)
181 except SALOME.SALOME_Exception, ex:
182 xmed.err(ex.details.text)
185 return FieldProxy(rfieldHandler)
187 def __rsub__(self, operande):
189 The user typed 'operande-self' where operande is not a field
190 proxy. This function process the situation.
192 # The operande is a numerical value (because otherwise, the
193 # "sub" method would have been called instead). We may apply
194 # the command '(self-operande)*(-1)' to activate the __sub__
195 # method of fieldpoxy.
197 #return (self-operande)*(-1)
199 # We prefer to apply a linear transformation because it can be
200 # done in one single request to the med calculator.
204 xmed.inf("Linear transformation %s%s*%s" % (offset, factor, self.fieldname))
206 rfieldHandler = xmed.calculator.lin(self.__fieldHandler, factor, offset)
207 except SALOME.SALOME_Exception, ex:
208 xmed.err(ex.details.text)
211 return FieldProxy(rfieldHandler)
213 def __mul__(self, operande):
215 This makes the multiplication of two fields or the
216 multiplication of a scalar to a field. It depends weither the
217 operande is a FieldProxy or a simple scalar numerical value.
220 if isinstance(operande, FieldProxy):
221 # The operande is an other field
222 xmed.inf("Multiplication of %s by %s"%(self.fieldname, operande.fieldname))
223 rfieldHandler = xmed.calculator.mul(self.__fieldHandler, operande.__fieldHandler)
225 # The operande is a scalar numerical value that must be
226 # considered as an offset in a linear transformation
229 xmed.inf("Scaling %s by factor %s" % (self.fieldname, factor))
230 rfieldHandler = xmed.calculator.lin(self.__fieldHandler, factor, offset)
231 except SALOME.SALOME_Exception, ex:
232 xmed.err(ex.details.text)
235 return FieldProxy(rfieldHandler)
237 def __rmul__(self, operande):
239 The user typed 'operande*self', we want to execute
240 'self*operande' to activate the __mul__ method of fieldpoxy.
244 def __div__(self, operande):
246 This makes the division of two fields or the division of field
247 by a scalar. It depends weither the operande is a FieldProxy
248 or a simple scalar numerical value.
251 if isinstance(operande, FieldProxy):
252 # The operande is an other field
253 xmed.inf("Division of %s by %s"%(self.fieldname, operande.fieldname))
254 rfieldHandler = xmed.calculator.div(self.__fieldHandler, operande.__fieldHandler)
256 # The operande is a scalar numerical value that must be
257 # considered as an offset in a linear transformation
260 xmed.inf("Scaling %s by factor 1/%s" % (self.fieldname, operande))
261 rfieldHandler = xmed.calculator.lin(self.__fieldHandler, factor, offset)
262 except SALOME.SALOME_Exception, ex:
263 xmed.err(ex.details.text)
266 return FieldProxy(rfieldHandler)
268 def __rdiv__(self, operande):
270 The user typed 'operande/self', we want to execute for each
271 value of the field the operation 'operande/value'.
273 xmed.inf("Division of %s by %s" % (operande, self.fieldname))
274 function = "%s/u"%operande
275 nbResComp = MEDOP.NBCOMP_DEFAULT
277 rfieldHandler = xmed.calculator.fct(self.__fieldHandler,function,nbResComp)
278 except SALOME.SALOME_Exception, ex:
279 xmed.err(ex.details.text)
282 return FieldProxy(rfieldHandler)
284 def __pow__(self, power):
286 This compute the power of the field to the specified value.
288 function = "abs(u)^%s"%power
289 return self.ope(function,duplicate=True)
293 This compute the absolute value of the field. We use here
295 return self.ope(function="abs(u)",duplicate=True)
299 This computes the negative of this field (when you type -f)
305 This creates a duplicate of the field. The whole data are
308 xmed.inf("Duplication of %s"%self.fieldname)
310 rfieldHandler = xmed.calculator.dup(self.__fieldHandler)
311 except SALOME.SALOME_Exception, ex:
312 xmed.err(ex.details.text)
315 return FieldProxy(rfieldHandler)
317 def ope(self, function, duplicate=True):
319 This can be used to apply a transformation function to this
320 field. The transformation is specified using a literal
321 equation given as a string where u stands for the field.
323 # _GBO_ TO BE IMPLEMENTED: the case where duplicate = False
324 # must modify the object itself and not create a new field
325 xmed.inf("Operate the equation \"%s\" to %s"%(function,self.fieldname))
327 rfieldHandler = xmed.calculator.fct(self.__fieldHandler,
329 MEDOP.NBCOMP_DEFAULT)
330 except SALOME.SALOME_Exception, ex:
331 xmed.err(ex.details.text)
334 return FieldProxy(rfieldHandler)
337 def __call__(self, restriction=None):
339 This could be used to return a fieldproxy binded on the same
340 fieldHandler than self, but with options that restrict the
341 usage to a domain specified by the given arguments (restricted
342 to a component, to a part of the mesh, ...).
344 xmed.wrn("Not implemented yet. Return the field itself")
345 self.__restriction = restriction
348 def update(self,name=None,iteration=None,order=None,source=None):
350 This function can be used to update the meta-data associated
351 to this field. It can modify the name, the iteration, the
352 order and the source.
355 name = self.fieldname
356 if iteration is None:
357 iteration = self.iteration
363 xmed.dataManager.updateFieldMetadata(self.id,name,iteration,order,source)
364 self.__fieldHandler.fieldname = name
365 self.__fieldHandler.iteration = iteration
366 self.__fieldHandler.order = order
367 self.__fieldHandler.source = source
368 # WARN: Note that you have to update directly the fieldHandler
369 # object because of the presence of the method __setattr__
370 # that make the proxy to this update method
372 # Finally, we have to notify the GUI for update of field prestations
373 #self.__notifyGui_update()
374 notifyGui_update(self.id)
376 # Print for visual control
377 print self.__repr__()
380 # ===================================================================
381 # Functions for events notification
382 # ===================================================================
384 # Note that these functions are not part of the class FieldProxy so
385 # that they could be used in another context than the FieldProxy instances
388 def __notifyGui(type, fieldId=-1):
389 medEvent = MEDOP.MedEvent(type, fieldId)
391 if not xmed.eventListenerIsRunning(): return
393 # Notify the GUI of the update event
394 xmed.eventListener.processMedEvent(medEvent)
397 def notifyGui_update(fieldId):
399 This function must be used to notify the GUI that the field
400 meta-data have changed so it could update the gui
401 presentations of this field.
403 __notifyGui(MEDOP.EVENT_UPDATE_FIELD,fieldId)
405 def notifyGui_add(fieldId):
406 __notifyGui(MEDOP.EVENT_ADDNEW_FIELD,fieldId)
408 def notifyGui_remove(fieldId):
409 __notifyGui(MEDOP.EVENT_DELETE_FIELD,fieldId)
411 def notifyGui_clean():
412 __notifyGui(MEDOP.EVENT_CLEAN_WORKSPACE)
415 # ===================================================================
417 # ===================================================================
420 # ===================================================================
421 if __name__ == "__main__":
422 # See test_medoperation.py