1 # Copyright (C) 2011-2016 CEA/DEN, EDF R&D
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Lesser General Public
5 # License as published by the Free Software Foundation; either
6 # version 2.1 of the License, or (at your option) any later version.
8 # This library is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # Lesser General Public License for more details.
13 # You should have received a copy of the GNU Lesser General Public
14 # License along with this library; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 # Author : Guillaume Boulant (EDF)
25 from medcalc.medcorba import factory
26 dataManager = factory.getDataManager()
27 calculator = factory.getCalculator()
29 # Some helper functions to deal with the fields and meshes
31 if sys.platform == "win32":
32 import MEDCouplingCompat as MEDCoupling
35 __mapTypeOfFieldLabel = {
36 MEDCoupling.ON_CELLS: "ON_CELLS",
37 MEDCoupling.ON_NODES: "ON_NODES",
38 MEDCoupling.ON_GAUSS_PT: "ON_GAUSS_PT",
39 MEDCoupling.ON_GAUSS_NE: "ON_GAUSS_NE"
42 def _typeOfFieldLabel(typeOfField):
43 # A field name could identify several MEDCoupling fields, that
44 # differ by their spatial discretization on the mesh (values on
45 # cells, values on nodes, ...). This spatial discretization is
46 # specified (at least) by the TypeOfField that is an integer value
53 return __mapTypeOfFieldLabel[typeOfField]
54 except IndexError as e:
58 def newFieldProxy(fieldHandlerId):
60 This creates a new FieldProxy wrapping the field whose
61 fieldHandlerId is passed in argument. The function requests the
62 DataManager to get the fieldHandler from its id.
64 fieldHandler = dataManager.getFieldHandler(fieldHandlerId)
65 return FieldProxy(fieldHandler)
68 # This define the map between attributes of a FieldProxy and those of
69 # the associated FieldHandler
70 PROXY_ATTRIBUTES_MAP = {"id":None,
76 "iteration":"iteration",
82 This object is a proxy to manipulate a remote MEDCoupling field
83 from within the SALOME python interpreter. Remote means that the
84 MEDCoupling field is in the SALOME container and not in the
85 client. See UserGuide class for detailed documentation of what can
86 be done with a field proxy.
88 def __init__( self, fieldHandler ):
90 This defines the wrapping on the field specified by its
93 self.__fieldHandler = fieldHandler
94 self.__restriction = None
95 print(self.__repr__())
97 def __getattr__(self, name ):
99 This method realizes the read proxy pattern toward the field
102 # WRN: Note that the modification of this function can lead to
103 # coercion problem. Modify this function with extrem care.
104 return getattr( self.__fieldHandler, name )
106 def __setattr__(self, name, value):
108 This method realizes the write proxy pattern toward the field
109 handler. Only some attributes are writable. The list is
110 specified in the PROXY_ATTRIBUTES_MAP table.
112 if name in list(PROXY_ATTRIBUTES_MAP.keys()):
113 if PROXY_ATTRIBUTES_MAP[name] is not None:
114 medcalc.wrn("The modification of this attribute can't be done that way")
115 msg="Use f.update(%s=\"%s\") instead to ensure synchronisation of data."
116 medcalc.inf(msg%(PROXY_ATTRIBUTES_MAP[name],value))
118 medcalc.err("The modification of the attribute %s is not possible"%name)
120 self.__dict__[name] = value
124 Return a string containing a printable representation of this
125 object (what is displayed when typing the variable name and
128 # We need first to update the handler because some data can
129 # have changed (the meshid for example in case of change of
131 # __GBO__ : TODO check the performance
132 self.__fieldHandler = dataManager.getFieldHandler(self.id)
133 text = "field name (id)\t = %s (%s)\n"%(self.fieldname, self.id)
134 text+= "mesh name (id) \t = %s (%s)\n"%(self.meshname,self.meshid)
135 text+= "discretization \t = %s\n"%_typeOfFieldLabel(self.type)
136 text+= "(iter, order) \t = (%s,%s)\n"%(str(self.iteration),str(self.order))
137 text+= "data source \t = %s"%self.source
142 This is what is displayed when you type 'print(myField)'. Note
143 that this function prints the values of the field and then you
144 must be aware that a huge amount of data could be
145 displayed. Moreover, it means that this operation triggers the
146 loading of the associated MEDCouplingFied data in the SALOME
149 text = dataManager.getFieldRepresentation(self.id)
152 def __add__(self, operande):
154 This makes the addition of two fields or the addition of a
155 scalar to a field. It depends weither the operande is a
156 FieldProxy or a simple scalar numerical value.
158 # The medcalc calculator could raise exceptions coming from
159 # MEDCoupling. Note that the fieldproxy instances are used
160 # from within the python console, and for ergonomic reason, we
161 # choose to not raise the possible exceptions to the console
162 # by a clear message. Keep this in mind for unit test. You
163 # have to test the return value, which should not be
164 # null. This principle is applyed for all operations.
166 if isinstance(operande, FieldProxy):
167 # The operande is an other field
168 medcalc.inf("Addition of %s and %s"%(self.fieldname, operande.fieldname))
169 rfieldHandler = calculator.add(self.__fieldHandler, operande.__fieldHandler)
171 # The operande is a scalar numerical value that must be
172 # considered as an offset in a linear transformation
175 medcalc.inf("Application of the offset %s to %s" % (offset, self.fieldname))
176 rfieldHandler = calculator.lin(self.__fieldHandler, factor, offset)
177 except SALOME.SALOME_Exception as ex:
178 medcalc.err(ex.details.text)
181 return FieldProxy(rfieldHandler)
183 def __radd__(self, operande):
185 The user typed 'operande+self', we replace by 'self+operande'
186 to automatically activate the __add__ method of fieldpoxy.
190 def __iadd__(self, operande):
192 These methods implements the augmented arithmetic assignments (+=)
194 medcalc.wrn("NOT IMPLEMENTED YET")
196 def __sub__(self,operande):
198 This makes the substraction of two fields or the substraction
199 of a scalar to a field. It depends weither the operande is a
200 FieldProxy or a simple scalar numerical value.
203 if isinstance(operande, FieldProxy):
204 # The operande is an other field
205 medcalc.inf("Substraction of %s by %s"%(self.fieldname, operande.fieldname))
206 rfieldHandler = calculator.sub(self.__fieldHandler, operande.__fieldHandler)
208 # The operande is a scalar numerical value that must be
209 # considered as an offset in a linear transformation
212 medcalc.inf("Application of the offset %s to %s" % (offset, self.fieldname))
213 rfieldHandler = calculator.lin(self.__fieldHandler, factor, offset)
214 except SALOME.SALOME_Exception as ex:
215 medcalc.err(ex.details.text)
218 return FieldProxy(rfieldHandler)
220 def __rsub__(self, operande):
222 The user typed 'operande-self' where operande is not a field
223 proxy. This function process the situation.
225 # The operande is a numerical value (because otherwise, the
226 # "sub" method would have been called instead). We may apply
227 # the command '(self-operande)*(-1)' to activate the __sub__
228 # method of fieldpoxy.
230 #return (self-operande)*(-1)
232 # We prefer to apply a linear transformation because it can be
233 # done in one single request to the med calculator.
237 medcalc.inf("Linear transformation %s%s*%s" % (offset, factor, self.fieldname))
239 rfieldHandler = calculator.lin(self.__fieldHandler, factor, offset)
240 except SALOME.SALOME_Exception as ex:
241 medcalc.err(ex.details.text)
244 return FieldProxy(rfieldHandler)
246 def __mul__(self, operande):
248 This makes the multiplication of two fields or the
249 multiplication of a scalar to a field. It depends weither the
250 operande is a FieldProxy or a simple scalar numerical value.
253 if isinstance(operande, FieldProxy):
254 # The operande is an other field
255 medcalc.inf("Multiplication of %s by %s"%(self.fieldname, operande.fieldname))
256 rfieldHandler = calculator.mul(self.__fieldHandler, operande.__fieldHandler)
258 # The operande is a scalar numerical value that must be
259 # considered as an offset in a linear transformation
262 medcalc.inf("Scaling %s by factor %s" % (self.fieldname, factor))
263 rfieldHandler = calculator.lin(self.__fieldHandler, factor, offset)
264 except SALOME.SALOME_Exception as ex:
265 medcalc.err(ex.details.text)
268 return FieldProxy(rfieldHandler)
270 def __rmul__(self, operande):
272 The user typed 'operande*self', we want to execute
273 'self*operande' to activate the __mul__ method of fieldpoxy.
277 def __div__(self, operande):
279 This makes the division of two fields or the division of field
280 by a scalar. It depends weither the operande is a FieldProxy
281 or a simple scalar numerical value.
284 if isinstance(operande, FieldProxy):
285 # The operande is an other field
286 medcalc.inf("Division of %s by %s"%(self.fieldname, operande.fieldname))
287 rfieldHandler = calculator.div(self.__fieldHandler, operande.__fieldHandler)
289 # The operande is a scalar numerical value that must be
290 # considered as an offset in a linear transformation
293 medcalc.inf("Scaling %s by factor 1/%s" % (self.fieldname, operande))
294 rfieldHandler = calculator.lin(self.__fieldHandler, factor, offset)
295 except SALOME.SALOME_Exception as ex:
296 medcalc.err(ex.details.text)
299 return FieldProxy(rfieldHandler)
301 def __rdiv__(self, operande):
303 The user typed 'operande/self', we want to execute for each
304 value of the field the operation 'operande/value'.
306 medcalc.inf("Division of %s by %s" % (operande, self.fieldname))
307 function = "%s/u"%operande
308 nbResComp = MEDCALC.NBCOMP_DEFAULT
310 rfieldHandler = calculator.fct(self.__fieldHandler,function,nbResComp)
311 except SALOME.SALOME_Exception as ex:
312 medcalc.err(ex.details.text)
315 return FieldProxy(rfieldHandler)
317 def __pow__(self, power):
319 This compute the power of the field to the specified value.
321 function = "abs(u)^%s"%power
322 return self.ope(function,duplicate=True)
326 This compute the absolute value of the field. We use here
328 return self.ope(function="abs(u)",duplicate=True)
332 This computes the negative of this field (when you type -f)
338 This creates a duplicate of the field. The whole data are
341 medcalc.inf("Duplication of %s"%self.fieldname)
343 rfieldHandler = calculator.dup(self.__fieldHandler)
344 except SALOME.SALOME_Exception as ex:
345 medcalc.err(ex.details.text)
348 return FieldProxy(rfieldHandler)
350 def ope(self, function, duplicate=True):
352 This can be used to apply a transformation function to this
353 field. The transformation is specified using a literal
354 equation given as a string where u stands for the field.
356 # _GBO_ TO BE IMPLEMENTED: the case where duplicate = False
357 # must modify the object itself and not create a new field
358 medcalc.inf("Operate the equation \"%s\" to %s"%(function,self.fieldname))
360 rfieldHandler = calculator.fct(self.__fieldHandler,
362 MEDCALC.NBCOMP_DEFAULT)
363 except SALOME.SALOME_Exception as ex:
364 medcalc.err(ex.details.text)
367 return FieldProxy(rfieldHandler)
369 def __call__(self, restriction=None):
371 This could be used to return a fieldproxy binded on the same
372 fieldHandler than self, but with options that restrict the
373 usage to a domain specified by the given arguments (restricted
374 to a component, to a part of the mesh, ...).
376 medcalc.wrn("Not implemented yet. Return the field itself")
377 self.__restriction = restriction
380 def update(self,name=None,iteration=None,order=None,source=None):
382 This function can be used to update the meta-data associated
383 to this field. It can modify the name, the iteration, the
384 order and the source.
387 name = self.fieldname
388 if iteration is None:
389 iteration = self.iteration
395 dataManager.updateFieldMetadata(self.id,name,iteration,order,source)
396 self.__fieldHandler.fieldname = name
397 self.__fieldHandler.iteration = iteration
398 self.__fieldHandler.order = order
399 self.__fieldHandler.source = source
400 # WARN: Note that you have to update directly the fieldHandler
401 # object because of the presence of the method __setattr__
402 # that make the proxy to this update method
404 # Finally, we have to notify the GUI for update of field prestations
405 #self.__notifyGui_update()
406 from medcalc.medevents import notifyGui_updateField
407 notifyGui_updateField(self.id)
409 # Print for visual control
410 print(self.__repr__())
415 # ===================================================================
416 # unit test functions
417 # ===================================================================
420 def TEST_typeOfFieldLabel():
421 print(typeOfFieldLabel(0))
422 print(typeOfFieldLabel(5))
425 # ===================================================================
426 if __name__ == "__main__":
427 TEST_typeOfFieldLabel()