1 # Copyright (C) 2011-2015 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 __mapTypeOfFieldLabel = {
32 MEDCoupling.ON_CELLS: "ON_CELLS",
33 MEDCoupling.ON_NODES: "ON_NODES",
34 MEDCoupling.ON_GAUSS_PT: "ON_GAUSS_PT",
35 MEDCoupling.ON_GAUSS_NE: "ON_GAUSS_NE"
38 def _typeOfFieldLabel(typeOfField):
39 # A field name could identify several MEDCoupling fields, that
40 # differ by their spatial discretization on the mesh (values on
41 # cells, values on nodes, ...). This spatial discretization is
42 # specified (at least) by the TypeOfField that is an integer value
49 return __mapTypeOfFieldLabel[typeOfField]
54 def newFieldProxy(fieldHandlerId):
56 This creates a new FieldProxy wrapping the field whose
57 fieldHandlerId is passed in argument. The function requests the
58 DataManager to get the fieldHandler from its id.
60 fieldHandler = dataManager.getFieldHandler(fieldHandlerId)
61 return FieldProxy(fieldHandler)
64 # This define the map between attributes of a FieldProxy and those of
65 # the associated FieldHandler
66 PROXY_ATTRIBUTES_MAP = {"id":None,
72 "iteration":"iteration",
78 This object is a proxy to manipulate a remote MEDCoupling field
79 from within the SALOME python interpreter. Remote means that the
80 MEDCoupling field is in the SALOME container and not in the
81 client. See UserGuide class for detailed documentation of what can
82 be done with a field proxy.
84 def __init__( self, fieldHandler ):
86 This defines the wrapping on the field specified by its
89 self.__fieldHandler = fieldHandler
90 self.__restriction = None
93 def __getattr__(self, name ):
95 This method realizes the read proxy pattern toward the field
98 # WRN: Note that the modification of this function can lead to
99 # coercion problem. Modify this function with extrem care.
100 return getattr( self.__fieldHandler, name )
102 def __setattr__(self, name, value):
104 This method realizes the write proxy pattern toward the field
105 handler. Only some attributes are writable. The list is
106 specified in the PROXY_ATTRIBUTES_MAP table.
108 if name in PROXY_ATTRIBUTES_MAP.keys():
109 if PROXY_ATTRIBUTES_MAP[name] is not None:
110 medcalc.wrn("The modification of this attribute can't be done that way")
111 msg="Use f.update(%s=\"%s\") instead to ensure synchronisation of data."
112 medcalc.inf(msg%(PROXY_ATTRIBUTES_MAP[name],value))
114 medcalc.err("The modification of the attribute %s is not possible"%name)
116 self.__dict__[name] = value
120 Return a string containing a printable representation of this
121 object (what is displayed when typing the variable name and
124 # We need first to update the handler because some data can
125 # have changed (the meshid for example in case of change of
127 # __GBO__ : TODO check the performance
128 self.__fieldHandler = dataManager.getFieldHandler(self.id)
129 text = "field name (id)\t = %s (%s)\n"%(self.fieldname, self.id)
130 text+= "mesh name (id) \t = %s (%s)\n"%(self.meshname,self.meshid)
131 text+= "discretization \t = %s\n"%_typeOfFieldLabel(self.type)
132 text+= "(iter, order) \t = (%s,%s)\n"%(str(self.iteration),str(self.order))
133 text+= "data source \t = %s"%self.source
138 This is what is displayed when you type 'print myField'. Note
139 that this function prints the values of the field and then you
140 must be aware that a huge amount of data could be
141 displayed. Moreover, it means that this operation triggers the
142 loading of the associated MEDCouplingFied data in the SALOME
145 text = dataManager.getFieldRepresentation(self.id)
148 def __add__(self, operande):
150 This makes the addition of two fields or the addition of a
151 scalar to a field. It depends weither the operande is a
152 FieldProxy or a simple scalar numerical value.
154 # The medcalc calculator could raise exceptions coming from
155 # MEDCoupling. Note that the fieldproxy instances are used
156 # from within the python console, and for ergonomic reason, we
157 # choose to not raise the possible exceptions to the console
158 # by a clear message. Keep this in mind for unit test. You
159 # have to test the return value, which should not be
160 # null. This principle is applyed for all operations.
162 if isinstance(operande, FieldProxy):
163 # The operande is an other field
164 medcalc.inf("Addition of %s and %s"%(self.fieldname, operande.fieldname))
165 rfieldHandler = calculator.add(self.__fieldHandler, operande.__fieldHandler)
167 # The operande is a scalar numerical value that must be
168 # considered as an offset in a linear transformation
171 medcalc.inf("Application of the offset %s to %s" % (offset, self.fieldname))
172 rfieldHandler = calculator.lin(self.__fieldHandler, factor, offset)
173 except SALOME.SALOME_Exception, ex:
174 medcalc.err(ex.details.text)
177 return FieldProxy(rfieldHandler)
179 def __radd__(self, operande):
181 The user typed 'operande+self', we replace by 'self+operande'
182 to automatically activate the __add__ method of fieldpoxy.
186 def __iadd__(self, operande):
188 These methods implements the augmented arithmetic assignments (+=)
190 medcalc.wrn("NOT IMPLEMENTED YET")
192 def __sub__(self,operande):
194 This makes the substraction of two fields or the substraction
195 of a scalar to a field. It depends weither the operande is a
196 FieldProxy or a simple scalar numerical value.
199 if isinstance(operande, FieldProxy):
200 # The operande is an other field
201 medcalc.inf("Substraction of %s by %s"%(self.fieldname, operande.fieldname))
202 rfieldHandler = calculator.sub(self.__fieldHandler, operande.__fieldHandler)
204 # The operande is a scalar numerical value that must be
205 # considered as an offset in a linear transformation
208 medcalc.inf("Application of the offset %s to %s" % (offset, self.fieldname))
209 rfieldHandler = calculator.lin(self.__fieldHandler, factor, offset)
210 except SALOME.SALOME_Exception, ex:
211 medcalc.err(ex.details.text)
214 return FieldProxy(rfieldHandler)
216 def __rsub__(self, operande):
218 The user typed 'operande-self' where operande is not a field
219 proxy. This function process the situation.
221 # The operande is a numerical value (because otherwise, the
222 # "sub" method would have been called instead). We may apply
223 # the command '(self-operande)*(-1)' to activate the __sub__
224 # method of fieldpoxy.
226 #return (self-operande)*(-1)
228 # We prefer to apply a linear transformation because it can be
229 # done in one single request to the med calculator.
233 medcalc.inf("Linear transformation %s%s*%s" % (offset, factor, self.fieldname))
235 rfieldHandler = calculator.lin(self.__fieldHandler, factor, offset)
236 except SALOME.SALOME_Exception, ex:
237 medcalc.err(ex.details.text)
240 return FieldProxy(rfieldHandler)
242 def __mul__(self, operande):
244 This makes the multiplication of two fields or the
245 multiplication of a scalar to a field. It depends weither the
246 operande is a FieldProxy or a simple scalar numerical value.
249 if isinstance(operande, FieldProxy):
250 # The operande is an other field
251 medcalc.inf("Multiplication of %s by %s"%(self.fieldname, operande.fieldname))
252 rfieldHandler = calculator.mul(self.__fieldHandler, operande.__fieldHandler)
254 # The operande is a scalar numerical value that must be
255 # considered as an offset in a linear transformation
258 medcalc.inf("Scaling %s by factor %s" % (self.fieldname, factor))
259 rfieldHandler = calculator.lin(self.__fieldHandler, factor, offset)
260 except SALOME.SALOME_Exception, ex:
261 medcalc.err(ex.details.text)
264 return FieldProxy(rfieldHandler)
266 def __rmul__(self, operande):
268 The user typed 'operande*self', we want to execute
269 'self*operande' to activate the __mul__ method of fieldpoxy.
273 def __div__(self, operande):
275 This makes the division of two fields or the division of field
276 by a scalar. It depends weither the operande is a FieldProxy
277 or a simple scalar numerical value.
280 if isinstance(operande, FieldProxy):
281 # The operande is an other field
282 medcalc.inf("Division of %s by %s"%(self.fieldname, operande.fieldname))
283 rfieldHandler = calculator.div(self.__fieldHandler, operande.__fieldHandler)
285 # The operande is a scalar numerical value that must be
286 # considered as an offset in a linear transformation
289 medcalc.inf("Scaling %s by factor 1/%s" % (self.fieldname, operande))
290 rfieldHandler = calculator.lin(self.__fieldHandler, factor, offset)
291 except SALOME.SALOME_Exception, ex:
292 medcalc.err(ex.details.text)
295 return FieldProxy(rfieldHandler)
297 def __rdiv__(self, operande):
299 The user typed 'operande/self', we want to execute for each
300 value of the field the operation 'operande/value'.
302 medcalc.inf("Division of %s by %s" % (operande, self.fieldname))
303 function = "%s/u"%operande
304 nbResComp = MEDCALC.NBCOMP_DEFAULT
306 rfieldHandler = calculator.fct(self.__fieldHandler,function,nbResComp)
307 except SALOME.SALOME_Exception, ex:
308 medcalc.err(ex.details.text)
311 return FieldProxy(rfieldHandler)
313 def __pow__(self, power):
315 This compute the power of the field to the specified value.
317 function = "abs(u)^%s"%power
318 return self.ope(function,duplicate=True)
322 This compute the absolute value of the field. We use here
324 return self.ope(function="abs(u)",duplicate=True)
328 This computes the negative of this field (when you type -f)
334 This creates a duplicate of the field. The whole data are
337 medcalc.inf("Duplication of %s"%self.fieldname)
339 rfieldHandler = calculator.dup(self.__fieldHandler)
340 except SALOME.SALOME_Exception, ex:
341 medcalc.err(ex.details.text)
344 return FieldProxy(rfieldHandler)
346 def ope(self, function, duplicate=True):
348 This can be used to apply a transformation function to this
349 field. The transformation is specified using a literal
350 equation given as a string where u stands for the field.
352 # _GBO_ TO BE IMPLEMENTED: the case where duplicate = False
353 # must modify the object itself and not create a new field
354 medcalc.inf("Operate the equation \"%s\" to %s"%(function,self.fieldname))
356 rfieldHandler = calculator.fct(self.__fieldHandler,
358 MEDCALC.NBCOMP_DEFAULT)
359 except SALOME.SALOME_Exception, ex:
360 medcalc.err(ex.details.text)
363 return FieldProxy(rfieldHandler)
365 def __call__(self, restriction=None):
367 This could be used to return a fieldproxy binded on the same
368 fieldHandler than self, but with options that restrict the
369 usage to a domain specified by the given arguments (restricted
370 to a component, to a part of the mesh, ...).
372 medcalc.wrn("Not implemented yet. Return the field itself")
373 self.__restriction = restriction
376 def update(self,name=None,iteration=None,order=None,source=None):
378 This function can be used to update the meta-data associated
379 to this field. It can modify the name, the iteration, the
380 order and the source.
383 name = self.fieldname
384 if iteration is None:
385 iteration = self.iteration
391 dataManager.updateFieldMetadata(self.id,name,iteration,order,source)
392 self.__fieldHandler.fieldname = name
393 self.__fieldHandler.iteration = iteration
394 self.__fieldHandler.order = order
395 self.__fieldHandler.source = source
396 # WARN: Note that you have to update directly the fieldHandler
397 # object because of the presence of the method __setattr__
398 # that make the proxy to this update method
400 # Finally, we have to notify the GUI for update of field prestations
401 #self.__notifyGui_update()
402 from medcalc.medevents import notifyGui_updateField
403 notifyGui_updateField(self.id)
405 # Print for visual control
406 print self.__repr__()
411 # ===================================================================
412 # unit test functions
413 # ===================================================================
416 def TEST_typeOfFieldLabel():
417 print typeOfFieldLabel(0)
418 print typeOfFieldLabel(5)
421 # ===================================================================
422 if __name__ == "__main__":
423 TEST_typeOfFieldLabel()