python.observation.esvalue

Created on Mon Aug 2 14:51:23 2021

@author: philippe@loco-labs.io

The python.observation.esvalue module contains the python.observation.esvalue_base.ESValue subclasses

ESValue is build around two attributes :

  • 'name' which is a simple String
  • 'value' which corresponds to a more or less complex object :

    • 'DatationValue' : value is a TimeSlot Object which represent a set of time intervals
    • 'LocationValue' : value is a Shapely Geometry which represent a set of polygons
    • 'PropertyValue' : value is a simple dictionary which specifies all the characteristics of a property
    • 'NamedValue' : value can be any simple object
    • 'ExternValue' : value can be any other object

This module groups the classes of the objects used in the python.observation.esobservation module :

and the parent class :

Documentation is available in other pages :

  • The concepts of 'ES value' are describe in this page.
  • The non-regression tests are at this page
  • Examples are here
  • The Json Standard for ESValue is define here
  1# -*- coding: utf-8 -*-
  2"""
  3Created on Mon Aug  2 14:51:23 2021
  4
  5@author: philippe@loco-labs.io
  6
  7The `python.observation.esvalue` module contains the `python.observation.esvalue_base.ESValue` subclasses
  8
  9ESValue is build around two attributes :
 10
 11- 'name' which is a simple String
 12- 'value' which corresponds to a more or less complex object :
 13
 14    - 'DatationValue' : value is a TimeSlot Object which represent a set of time intervals
 15    - 'LocationValue' : value is a Shapely Geometry which represent a set of polygons
 16    - 'PropertyValue' : value is a simple dictionary which specifies all the characteristics of a property
 17    - 'NamedValue'    : value can be any simple object
 18    - 'ExternValue'   : value can be any other object
 19
 20<img src="https://loco-philippe.github.io/ES/ESValue_class.png" width="800">
 21
 22This module groups the classes of the objects used in the `python.observation.esobservation` module :
 23
 24- `DatationValue`,
 25- `LocationValue`,
 26- `PropertyValue`,
 27- `NamedValue`
 28- `ExternValue`
 29
 30and the parent class :
 31
 32- `python.observation.esvalue_base.ESValue`
 33
 34Documentation is available in other pages :
 35    
 36- The concepts of 'ES value' are describe in 
 37[this page](https://github.com/loco-philippe/Environmental-Sensing/wiki/ESValue).
 38- The non-regression tests are at 
 39[this page](https://github.com/loco-philippe/Environmental-Sensing/blob/main/python/Tests/test_esvalue.py)
 40- Examples are 
 41[here](https://github.com/loco-philippe/Environmental-Sensing/tree/main/python/Examples)
 42- The Json Standard for ESValue is define 
 43[here](https://github.com/loco-philippe/Environmental-Sensing/tree/main/documentation/ESJSON-Standard.pdf)
 44
 45
 46
 47"""
 48import json
 49import geojson
 50import shapely.geometry
 51import datetime
 52from geopy import distance
 53from copy import copy
 54from openlocationcode import openlocationcode
 55
 56from observation.esconstante import ES, _classval
 57from observation.esvalue_base import ESValueEncoder, ESValue
 58from observation.timeslot import TimeSlot
 59
 60
 61class DatationValue(ESValue):   # !!! début ESValue
 62    # %% dat
 63    """
 64    This class represent Time (instant, interval or set of intervals).
 65
 66    *Attributes (for @property see methods)* :
 67
 68    - **value** : TimeSlot object (instant, interval or list of interval)
 69    - **name** : String
 70
 71    The methods defined in this class are :
 72
 73    *constructor (@classmethod)*
 74
 75    - `DatationValue.Simple`  (instant)
 76    - `DatationValue.Box`     (interval)
 77    - `DatationValue.from_obj`(see  `ESValue.from_obj`)
 78
 79
 80    *getters*
 81
 82    - `DatationValue.getInstant`
 83    - `DatationValue.getInterval`
 84    - `DatationValue.vSimple`
 85    - `DatationValue.vInterval`
 86    - `DatationValue.link`    
 87    """
 88    @classmethod
 89    def Simple(cls, instant):
 90        '''DatationValue built with a time value (instant) '''
 91        return cls(slot=TimeSlot(instant), name='instant')
 92
 93    @classmethod
 94    def Box(cls, bounds):
 95        '''DatationValue built from a tuple or list box coordinates (tmin, tmax)'''
 96        if isinstance(bounds, cls):
 97            bound = bounds.bounds
 98        else:
 99            bound = bounds
100        return cls(val=TimeSlot(bound), name='interval')
101
102    @classmethod
103    def from_obj(cls, bs):
104        ''' ESValue function (see ESValue.from_obj)'''
105        return ESValue.from_obj(bs, ES.dat_clsName, simple=False)
106
107    def __init__(self, val=ES.nullDate, name=ES.nullName):
108        '''
109        DatationValue constructor.
110
111        *Parameters*
112
113        - **val** :  compatible Timeslot Value (default nullDate)
114        - **name** :  string (default nullName)
115        '''
116        ESValue.__init__(self)
117        if isinstance(val, self.__class__):
118            self.name = val.name
119            self.value = val.value
120            return
121        if not val is None:
122            try:
123                self.value = TimeSlot(val)
124            except:
125                if not name:
126                    name = val
127                else:
128                    raise ESValueError('name and val inconsistent')
129        if self.name == ES.nullName and isinstance(name, str) and name != ES.nullName:
130            self.name = name
131
132    @staticmethod
133    def boundingBox(listValue):
134        ''' return a tuple (datmin, datmax) with bounds values'''
135        return [min([val.value.slot[0].start for val in listValue]),
136                max([val.value.slot[len(val.value) - 1].end for val in listValue])]
137        # return (TimeSlot.form(self.slot[0].start), TimeSlot.form(self.slot[len(self) - 1].end))
138
139    def getInstant(self):
140        '''return datetime if 'instant', none else'''
141        if self.value.stype == 'instant':
142            return self.value. slot[0][0]
143        return None
144
145    def getInterval(self):
146        '''return [datetime t1, datetime t2] if 'interval', none else'''
147        if self.value.stype == 'interval':
148            return self.value. slot[0]
149        return None
150
151    def link(self, other):
152        '''
153        return the link (string) between self.value and other.value :
154        - equals     : if self and other are the same
155        - disjoint   : if self's intervals and other's intervals are all disjoint
156        - within     : if all self's intervals are included in other's intervals
157        - contains   : if all other's intervals are included in self's intervals
158        - intersects : in the others cases'''
159        if self.isEqual(other, name=False):
160            return 'equals'
161        return self.value.link(other.value)[0]
162
163    @staticmethod
164    def nullValue():
165        ''' return nullDate value'''
166        return TimeSlot(ES.nullDate)
167
168    def vInterval(self, encoded=True, encode_format='json'):
169        """return [t1, t2] with t1, t2 - Mini, maxi of the TimeSlot (timestamp or datetime).
170
171        *Parameters*
172
173        - **encode_format**    : string (default 'json')- choice for return format (json, cbor)
174
175        *Returns*
176
177        - **JSON with timestamp or list with datetime**
178        """
179        return self.value.Bounds.json(encoded=encoded, encode_format=encode_format)
180
181    def vSimple(self, string=False, **kwargs):
182        """return a datetime : middle of the TimeSlot."""
183        if string:
184            return self.value.instant.isoformat(**kwargs)
185        return self.value.instant
186
187    def _jsonValue(self, **option):
188        '''return a json/cbor/dict for the value (TimeSlot) '''
189        return self.value.json(**option)
190
191
192class LocationValue(ESValue):              # !!! début LocationValue
193    # %% loc
194    """
195    This class represent the Location of an Observation (point, polygon).
196
197    *Attributes (for @property see methods)* :
198
199    - **value** : Shapely object (point, polygon)
200    - **name** : String
201
202    The methods defined in this class are :
203
204    *constructor (@classmethod)*
205
206    - `LocationValue.Simple`   (point)
207    - `LocationValue.Box`
208    - `LocationValue.from_obj` (see  `ESValue.from_obj`)
209
210    *getters (@property)*
211
212    - `LocationValue.coords`
213    - `LocationValue.coorInv`
214
215    *getters*
216
217    - `LocationValue.getPoint`
218    - `LocationValue.vSimple`
219    - `LocationValue.vPointInv`
220    - `LocationValue.vPointX`
221    - `LocationValue.vPointY`
222    - `LocationValue.vCodePlus`
223    - `LocationValue.link`
224    """
225    @classmethod
226    def Simple(cls, coord):
227        '''return LocationValue built with tuple or list coordinates (x,y)'''
228        return cls(shape=shapely.geometry.Point(*coord), name='point')
229
230    @classmethod
231    def Box(cls, bounds, ccw=True):
232        '''return LocationValue built with tuple or list box coordinates (minx, miny, maxx, maxy)'''
233        if isinstance(bounds, cls):
234            bound = bounds.bounds
235        else:
236            bound = bounds
237        return cls(val=shapely.geometry.box(*bound, ccw), name='box')
238
239    @classmethod
240    def from_obj(cls, bs):
241        ''' ESValue function (see ESValue.from_obj)'''
242        return ESValue.from_obj(bs, ES.loc_clsName, simple=False)
243
244    def __init__(self, val=ES.nullCoor, name=ES.nullName):
245        '''
246        LocationValue constructor.
247
248        *Parameters*
249
250        - **val** :  compatible shapely.geometry.Point (or Polygon) Value (default nullCoor)
251        - **name** :  string (default nullName)
252        '''
253        ESValue.__init__(self)
254        if isinstance(val, self.__class__):
255            self.name = val.name
256            self.value = val.value
257            return
258        if isinstance(val, (shapely.geometry.multipoint.MultiPoint,
259                            shapely.geometry.point.Point,
260                            shapely.geometry.polygon.Polygon,
261                            shapely.geometry.multipolygon.MultiPolygon)):
262            self.value = val
263        elif not val is None:
264            if isinstance(val, str) and not name:
265                name = val
266            else:
267                self.value = self._gshape(val)
268        if self.name == ES.nullName and isinstance(name, str) and name != ES.nullName:
269            self.name = name
270
271    def __lt__(self, other):
272        ''' return minimal distance between a fixed point'''
273        if self.__class__.__name__ != other.__class__.__name__:
274            return hash(self) < hash(other)
275        # if self.coorInv == ES.nullCoor:
276        if self.coorInv == other.coorInv:
277            return self.name < other.name
278        return distance.distance(self.coorInv, ES.distRef) <  \
279            distance.distance(other.coorInv, ES.distRef)
280
281    @property
282    def __geo_interface__(self):
283        return json.loads(json.dumps(self.value.__geo_interface__, cls=ESValueEncoder))
284
285    @staticmethod
286    def boundingBox(listValue):
287        ''' return a tuple (xmin, ymin, xmax, ymax) with bounds values'''
288        return [min([val.value.bounds[0] for val in listValue]),
289                min([val.value.bounds[1] for val in listValue]),
290                max([val.value.bounds[2] for val in listValue]),
291                max([val.value.bounds[3] for val in listValue])]
292
293    @property
294    def coords(self):
295        ''' return geoJson coordinates (list)'''
296        if isinstance(self.value, shapely.geometry.polygon.Polygon):
297            coords = [list(self.value.exterior.coords)]
298        elif isinstance(self.value, shapely.geometry.point.Point):
299            coords = list(self.value.coords[0])
300        elif isinstance(self.value, shapely.geometry.linestring.LineString):
301            coords = list(self.value.coords)
302        else:
303            coords = ES.nullCoor
304        return json.loads(json.dumps(coords, cls=ESValueEncoder))
305
306    @property
307    def coorInv(self):
308        '''list (@property) : vSimple inverse coordinates [vSimple[1], vSimple[0]]'''
309        return [self.vSimple()[1], self.vSimple()[0]]
310
311    def getPoint(self):
312        ''' return a list with point coordinates [x, y] if the shape is a point, else none'''
313        if isinstance(self.value, shapely.geometry.point.Point):
314            return [self.value.x, self.value.y]
315        return None
316
317    def link(self, other):
318        '''
319        return the link (string) between self.value and other.value :
320        - equals     : if self and other are the same
321        - disjoint   : if self's shape and other's shape are disjoint
322        - within     : if other's shape contains self's shape
323        - contains   : if self's shape contains other's shape
324        - intersects : in the others cases'''
325        if self.isEqual(other, name=False):
326            return 'equals'
327        if self.value.equals(other.value):
328            return 'equals'
329        if self.value.contains(other.value):
330            return 'contains'
331        if self.value.within(other.value):
332            return 'within'
333        if self.value.disjoint(other.value):
334            return 'disjoint'
335        if self.value.intersects(other.value):
336            return 'intersects'
337
338    @staticmethod
339    def nullValue():
340        ''' return nullPosition value'''
341        return LocationValue._gshape(ES.nullCoor)
342
343    def vCodePlus(self):
344        ''' return CodePlus value (string) of the point property value'''
345        return openlocationcode.encode(self.vSimple(False)[1], self.vSimple(False)[0])
346
347    def vSimple(self, string=False):
348        ''' return simple value (centroid coordinates for the shape : 
349            [x, y]) in a string format or in a object format'''
350        if string:
351            return json.dumps([round(self.value.centroid.x, 5), round(self.value.centroid.y, 5)], cls=ESValueEncoder)
352        return [round(self.value.centroid.x, 5), round(self.value.centroid.y, 5)]
353
354    def vPointInv(self, string=False):
355        ''' return point (property) with inversed vSimple coordinates in a string format or
356        in a list format [y, x]'''
357        if string:
358            return json.dumps([self.vSimple()[1], self.vSimple()[0]], cls=ESValueEncoder)
359        return [self.vSimple()[1], self.vSimple()[0]]
360
361    def vPointX(self):
362        ''' return point (property) coordinates x '''
363        return self.vSimple()[0]
364
365    def vPointY(self):
366        ''' return point (property) coordinates y '''
367        return self.vSimple()[1]
368
369    def _jsonValue(self, **kwargs):
370        ''' return geoJson coordinates'''
371        if 'geojson' in kwargs and kwargs['geojson']:
372            return self.__geo_interface__
373        return self.coords
374
375    @staticmethod
376    def _gshape(coord):
377        ''' transform a GeoJSON coordinates (list) into a shapely geometry'''
378        if isinstance(coord, tuple):
379            coor = json.dumps(list(coord), cls=ESValueEncoder)
380        elif isinstance(coord, list):
381            coor = json.dumps(coord, cls=ESValueEncoder)
382        elif isinstance(coord, dict):
383            coor = json.dumps(coord, cls=ESValueEncoder)
384        elif isinstance(coord, str):
385            coor = coord
386        else:
387            coor = copy(coord)
388        for tpe in ["Point", "MultiPoint", "Polygon", "MultiPolygon"]:
389            try:
390                return shapely.geometry.shape(geojson.loads('{"type":"' + tpe + '","coordinates":' + coor + '}'))
391            except:
392                pass
393        raise ESValueError('coordinates unconsistent')
394        return None
395
396
397class PropertyValue(ESValue):              # !!! début ESValue
398    # %% prp
399    """
400    This class represents the Property of an Observation.
401
402    *Attributes (for @property see methods)* :
403
404    - **value** : dict
405    - **name** : String
406
407    The methods defined in this class are :
408
409    *constructor (@classmethod)*
410
411    - `PropertyValue.Simple`   (property type)
412    - `PropertyValue.Box`      (set of property type)
413    - `PropertyValue.from_obj` (see  `ESValue.from_obj`)
414
415    *getters*
416
417    - `PropertyValue.vSimple`
418    - `PropertyValue.link`
419    """
420    @classmethod
421    def Simple(cls, prp, name='simple', prp_dict=False):
422        '''PropertyValue built with a value (property type) '''
423        return cls(val={ES.prp_type: prp}, name=name, prp_dict=prp_dict)
424
425    @classmethod
426    def Box(cls, prp, name='box', prp_dict=False):
427        '''PropertyValue built with a value (property type) '''
428        return cls(val={ES.prp_type: prp}, name=name, prp_dict=prp_dict)
429
430    @classmethod
431    def from_obj(cls, bs):
432        ''' ESValue function (see ESValue.from_obj)'''
433        return ESValue.from_obj(bs, ES.prp_clsName, simple=False)
434
435    def __init__(self, val=ES.nullPrp, name=ES.nullName, prp_dict=False):
436        '''
437        PropertyValue constructor.
438
439        *Parameters*
440
441        - **val** :  property dict or json string (default nullPrp)
442        - **name** :  string (default nullName)
443        - **prp_dict** : boolean(default False) - if True type property has to be in the type dictionary
444        '''
445        ESValue.__init__(self)
446        if isinstance(val, self.__class__):
447            self.name = val.name
448            self.value = val.value
449            return
450        if not val is None and name == ES.prp_type:
451            name = None
452            val = {ES.prp_type: val}
453        elif isinstance(val, str) and isinstance(name, str) and name != ES.nullName:
454            val = {name: val}
455        if isinstance(val, dict):
456            if len(val) > 0 and isinstance(list(val.values())[0], dict):
457                self.name = list(val.keys())[0]
458                self.value |= val[list(val.keys())[0]]
459            else:
460                self.value |= val
461        elif isinstance(val, str):
462            name = val
463        # elif not val is None: raise ESValueError('type data not compatible with PropertyValue')
464        # else: raise ESValueError('type data not compatible with PropertyValue')
465
466        if self.name == ES.nullName and isinstance(name, str) and name != ES.nullName:
467            self.name = name
468        if not ES.prp_type in self.value:
469            raise ESValueError("type property not defined")
470        if not isinstance(self.value[ES.prp_type], list):
471            if prp_dict and not self.value[ES.prp_type] in ES.prop:
472                raise ESValueError(
473                    "property not present in standard dictionnary")
474            if prp_dict:
475                self.value[ES.prp_unit] = ES.prop[self.value[ES.prp_type]][5]
476
477    def __lt__(self, other):
478        """lower if string simple value + name is lower"""
479        if self.__class__.__name__ != other.__class__.name:
480            return hash(self) < hash(other)
481        return self.simple + self.name < other.simple + other.name
482
483    @staticmethod
484    def boundingBox(listValue):
485        ''' return a tuple with 'prp' values'''
486        return [val.value['prp'] for val in listValue]
487
488    def link(self, other):
489        '''
490        return the link (string) between self.value and other.value :
491        - equals     : if self and other are the same
492        - disjoint   : if the self's key/val are all different from other's key/val
493        - within     : if all self's key/val are included in other's key/val
494        - contains   : if all other's key/val are included in self's key/val
495        - intersects : in the others cases'''
496        if self.isEqual(other, name=False):
497            return 'equals'
498        sprp = self._setprp(self.value[ES.prp_type])
499        oprp = self._setprp(other.value[ES.prp_type])
500        if oprp == sprp:
501            union = other.value | self.value
502            union2 = self.value | other.value
503            if union == self.value and union2 == self.value:
504                return 'within'
505            if union == other.value and union2 == other.value:
506                return 'contains'
507            if union == union2:
508                return 'disjoint'
509            return 'intersects'
510        if sprp == sprp | oprp:
511            return 'contains'
512        if oprp == sprp | oprp:
513            return 'within'
514        if oprp & sprp == set():
515            return 'disjoint'
516        else:
517            return 'intersects'
518        return 'undefined'
519
520    @staticmethod
521    def nullValue():
522        ''' return nullPrp value'''
523        return {ES.prp_type: ES.nullDict, ES.prp_unit: ES.prop[ES.nullDict][5]}
524
525    def vSimple(self, string=False):
526        ''' return simple value (type for the property) in a string format or in a object format'''
527        simple = ES.nullDict
528        if ES.prp_type in self.value:
529            simple = self.value[ES.prp_type]
530        if string:
531            return json.dumps(simple, cls=ESValueEncoder)
532        return simple
533
534    def _jsonValue(self, **kwargs):
535        option = {'encoded': False} | kwargs
536        li = {}
537        for k, v in self.value.items():
538            if k in [ES.prp_type, ES.prp_unit, ES.prp_sampling, ES.prp_appli, ES.prp_EMFId]:
539                if v != ES.nullDict:
540                    li[k] = v
541            elif k in [ES.prp_period, ES.prp_interval, ES.prp_uncertain]:
542                if v != ES.nullInt:
543                    li[k] = v
544            else:
545                li[k] = v
546        if option['encoded']:
547            return json.dumps(li, ensure_ascii=False, cls=ESValueEncoder)
548        return li
549
550    @staticmethod
551    def _setprp(val):
552        if isinstance(val, list):
553            return set(val)
554        return {val}
555
556
557class NamedValue (ESValue):               # !!! début ResValue
558    # %% nam
559    '''This class represent a simple value with an associated string.
560
561    *Attributes (for @property see methods)* :
562
563    - **value** : any json object
564    - **name** : String
565
566    The methods defined in this class are :
567
568    *constructor*
569
570    - `NamedValue.from_obj` (see  `ESValue.from_obj`)
571
572    *getters*
573
574    - `NamedValue.vSimple`
575    '''
576    @classmethod
577    def from_obj(cls, bs):
578        ''' ESValue function (see ESValue.from_obj)'''
579        return ESValue.from_obj(bs, ES.nam_clsName, simple=False)
580
581    def __init__(self, val=ES.nullVal, name=ES.nullName):
582        '''
583        NamedValue constructor.
584
585        *Parameters*
586
587        - **val** :  any simple object (default nullVal)
588        - **name** : string (default nullName)
589        '''
590        ESValue.__init__(self)
591        if isinstance(val, self.__class__):
592            self.name = val.name
593            self.value = val.value
594            return
595        self.value = ESValue._castsimple(val)
596        if self.name == ES.nullName and isinstance(name, str) and name != ES.nullName:
597            self.name = name
598
599    @staticmethod
600    def nullValue():
601        ''' return nullVal value'''
602        return ES.nullVal
603
604    def vSimple(self, string=False):
605        '''return float value in string or object format'''
606        from util import util
607        if string:
608            return str(util.cast(self.value, dtype='simple'))
609        return util.cast(self.value, dtype='simple')
610
611    def _jsonValue(self, **option):
612        '''return the value '''
613        if isinstance(self.value, (int, str, float, bool, list, dict,
614                                   datetime.datetime, type(None), bytes)):
615            return self.value
616        if isinstance(self.value, tuple):
617            return list(self.value)
618
619
620class ExternValue (ESValue):               # !!! début ResValue
621    # %% ext
622    '''This class represent a complex (extern) value with an associated string.
623
624    *Attributes (for @property see methods)* :
625
626    - **value** : any object
627    - **name** : String
628
629    The methods defined in this class are :
630
631    *constructor*
632
633    - `ExternValue.from_obj` (see  `ESValue.from_obj`)
634
635    *getters*
636
637    - `ExternValue.vSimple`
638    '''
639    @classmethod
640    def from_obj(cls, bs):
641        ''' ESValue function (see ESValue.from_obj)'''
642        return ESValue.from_obj(bs, ES.ext_clsName, simple=False)
643
644    def __init__(self, val=ES.nullExternVal, name=ES.nullName, className=None):
645        '''
646        ExternValue constructor.
647
648        *Parameters*
649
650        - **val** :  any simple object (default nullVal)
651        - **name** : string (default nullName)
652
653        '''
654        ESValue.__init__(self)
655        if isinstance(val, self.__class__):
656            self.name = val.name
657            self.value = val.value
658            return
659        #self.value = ESValue.from_obj(val, classname=className)
660        if val == ES.nullExternVal and name == ES.nullName:
661            return
662        if not className:
663            className = val.__class__.__name__
664        if className in _classval():
665            self.value = _classval()[className](val)
666        else:
667            raise ESValueError('class name inconsistent with ExternValue')
668        if self.name == ES.nullName and isinstance(name, str) and name != ES.nullName:
669            self.name = name
670
671    @staticmethod
672    def nullValue():
673        ''' return nullVal value'''
674        return ES.nullExternVal
675
676    def vSimple(self, string=False):
677        '''return conversion from value to float'''
678        from util import util
679        if string:
680            return str(util.cast(self.value, dtype='simple'))
681        return util.cast(self.value, dtype='simple')
682
683    def _jsonValue(self, **option):
684        '''return a json object for the value '''
685        if self.value.__class__.__name__ in ['Field', 'Dataset', 'Observation']:
686            return self.value.json(encoded=False, encode_format='json')
687        if isinstance(self.value, (int, str, float, bool, list, tuple, dict, datetime.datetime, type(None), bytes)):
688            return self.value
689        if isinstance(self.value, (DatationValue, LocationValue, PropertyValue, NamedValue, ExternValue)):
690            return self.value.json(encoded=False, encode_format='json')
691        try:
692            return self.value.to_json(encoded=False, encode_format='json',
693                                      json_info=False, json_res_index=True, json_param=True)
694        except:
695            return object.__repr__(self.value)
696
697
698class ESValueError(Exception):
699    # %% ES except
700    ''' ESValue Exception'''
701    pass
class DatationValue(observation.esvalue_base.ESValue):
 62class DatationValue(ESValue):   # !!! début ESValue
 63    # %% dat
 64    """
 65    This class represent Time (instant, interval or set of intervals).
 66
 67    *Attributes (for @property see methods)* :
 68
 69    - **value** : TimeSlot object (instant, interval or list of interval)
 70    - **name** : String
 71
 72    The methods defined in this class are :
 73
 74    *constructor (@classmethod)*
 75
 76    - `DatationValue.Simple`  (instant)
 77    - `DatationValue.Box`     (interval)
 78    - `DatationValue.from_obj`(see  `ESValue.from_obj`)
 79
 80
 81    *getters*
 82
 83    - `DatationValue.getInstant`
 84    - `DatationValue.getInterval`
 85    - `DatationValue.vSimple`
 86    - `DatationValue.vInterval`
 87    - `DatationValue.link`    
 88    """
 89    @classmethod
 90    def Simple(cls, instant):
 91        '''DatationValue built with a time value (instant) '''
 92        return cls(slot=TimeSlot(instant), name='instant')
 93
 94    @classmethod
 95    def Box(cls, bounds):
 96        '''DatationValue built from a tuple or list box coordinates (tmin, tmax)'''
 97        if isinstance(bounds, cls):
 98            bound = bounds.bounds
 99        else:
100            bound = bounds
101        return cls(val=TimeSlot(bound), name='interval')
102
103    @classmethod
104    def from_obj(cls, bs):
105        ''' ESValue function (see ESValue.from_obj)'''
106        return ESValue.from_obj(bs, ES.dat_clsName, simple=False)
107
108    def __init__(self, val=ES.nullDate, name=ES.nullName):
109        '''
110        DatationValue constructor.
111
112        *Parameters*
113
114        - **val** :  compatible Timeslot Value (default nullDate)
115        - **name** :  string (default nullName)
116        '''
117        ESValue.__init__(self)
118        if isinstance(val, self.__class__):
119            self.name = val.name
120            self.value = val.value
121            return
122        if not val is None:
123            try:
124                self.value = TimeSlot(val)
125            except:
126                if not name:
127                    name = val
128                else:
129                    raise ESValueError('name and val inconsistent')
130        if self.name == ES.nullName and isinstance(name, str) and name != ES.nullName:
131            self.name = name
132
133    @staticmethod
134    def boundingBox(listValue):
135        ''' return a tuple (datmin, datmax) with bounds values'''
136        return [min([val.value.slot[0].start for val in listValue]),
137                max([val.value.slot[len(val.value) - 1].end for val in listValue])]
138        # return (TimeSlot.form(self.slot[0].start), TimeSlot.form(self.slot[len(self) - 1].end))
139
140    def getInstant(self):
141        '''return datetime if 'instant', none else'''
142        if self.value.stype == 'instant':
143            return self.value. slot[0][0]
144        return None
145
146    def getInterval(self):
147        '''return [datetime t1, datetime t2] if 'interval', none else'''
148        if self.value.stype == 'interval':
149            return self.value. slot[0]
150        return None
151
152    def link(self, other):
153        '''
154        return the link (string) between self.value and other.value :
155        - equals     : if self and other are the same
156        - disjoint   : if self's intervals and other's intervals are all disjoint
157        - within     : if all self's intervals are included in other's intervals
158        - contains   : if all other's intervals are included in self's intervals
159        - intersects : in the others cases'''
160        if self.isEqual(other, name=False):
161            return 'equals'
162        return self.value.link(other.value)[0]
163
164    @staticmethod
165    def nullValue():
166        ''' return nullDate value'''
167        return TimeSlot(ES.nullDate)
168
169    def vInterval(self, encoded=True, encode_format='json'):
170        """return [t1, t2] with t1, t2 - Mini, maxi of the TimeSlot (timestamp or datetime).
171
172        *Parameters*
173
174        - **encode_format**    : string (default 'json')- choice for return format (json, cbor)
175
176        *Returns*
177
178        - **JSON with timestamp or list with datetime**
179        """
180        return self.value.Bounds.json(encoded=encoded, encode_format=encode_format)
181
182    def vSimple(self, string=False, **kwargs):
183        """return a datetime : middle of the TimeSlot."""
184        if string:
185            return self.value.instant.isoformat(**kwargs)
186        return self.value.instant
187
188    def _jsonValue(self, **option):
189        '''return a json/cbor/dict for the value (TimeSlot) '''
190        return self.value.json(**option)

This class represent Time (instant, interval or set of intervals).

Attributes (for @property see methods) :

  • value : TimeSlot object (instant, interval or list of interval)
  • name : String

The methods defined in this class are :

constructor (@classmethod)

getters

DatationValue(val=None, name='')
108    def __init__(self, val=ES.nullDate, name=ES.nullName):
109        '''
110        DatationValue constructor.
111
112        *Parameters*
113
114        - **val** :  compatible Timeslot Value (default nullDate)
115        - **name** :  string (default nullName)
116        '''
117        ESValue.__init__(self)
118        if isinstance(val, self.__class__):
119            self.name = val.name
120            self.value = val.value
121            return
122        if not val is None:
123            try:
124                self.value = TimeSlot(val)
125            except:
126                if not name:
127                    name = val
128                else:
129                    raise ESValueError('name and val inconsistent')
130        if self.name == ES.nullName and isinstance(name, str) and name != ES.nullName:
131            self.name = name

DatationValue constructor.

Parameters

  • val : compatible Timeslot Value (default nullDate)
  • name : string (default nullName)
@classmethod
def Simple(cls, instant):
89    @classmethod
90    def Simple(cls, instant):
91        '''DatationValue built with a time value (instant) '''
92        return cls(slot=TimeSlot(instant), name='instant')

DatationValue built with a time value (instant)

@classmethod
def Box(cls, bounds):
 94    @classmethod
 95    def Box(cls, bounds):
 96        '''DatationValue built from a tuple or list box coordinates (tmin, tmax)'''
 97        if isinstance(bounds, cls):
 98            bound = bounds.bounds
 99        else:
100            bound = bounds
101        return cls(val=TimeSlot(bound), name='interval')

DatationValue built from a tuple or list box coordinates (tmin, tmax)

@classmethod
def from_obj(cls, bs):
103    @classmethod
104    def from_obj(cls, bs):
105        ''' ESValue function (see ESValue.from_obj)'''
106        return ESValue.from_obj(bs, ES.dat_clsName, simple=False)

ESValue function (see ESValue.from_obj)

@staticmethod
def boundingBox(listValue):
133    @staticmethod
134    def boundingBox(listValue):
135        ''' return a tuple (datmin, datmax) with bounds values'''
136        return [min([val.value.slot[0].start for val in listValue]),
137                max([val.value.slot[len(val.value) - 1].end for val in listValue])]
138        # return (TimeSlot.form(self.slot[0].start), TimeSlot.form(self.slot[len(self) - 1].end))

return a tuple (datmin, datmax) with bounds values

def getInstant(self):
140    def getInstant(self):
141        '''return datetime if 'instant', none else'''
142        if self.value.stype == 'instant':
143            return self.value. slot[0][0]
144        return None

return datetime if 'instant', none else

def getInterval(self):
146    def getInterval(self):
147        '''return [datetime t1, datetime t2] if 'interval', none else'''
148        if self.value.stype == 'interval':
149            return self.value. slot[0]
150        return None

return [datetime t1, datetime t2] if 'interval', none else

@staticmethod
def nullValue():
164    @staticmethod
165    def nullValue():
166        ''' return nullDate value'''
167        return TimeSlot(ES.nullDate)

return nullDate value

def vInterval(self, encoded=True, encode_format='json'):
169    def vInterval(self, encoded=True, encode_format='json'):
170        """return [t1, t2] with t1, t2 - Mini, maxi of the TimeSlot (timestamp or datetime).
171
172        *Parameters*
173
174        - **encode_format**    : string (default 'json')- choice for return format (json, cbor)
175
176        *Returns*
177
178        - **JSON with timestamp or list with datetime**
179        """
180        return self.value.Bounds.json(encoded=encoded, encode_format=encode_format)

return [t1, t2] with t1, t2 - Mini, maxi of the TimeSlot (timestamp or datetime).

Parameters

  • encode_format : string (default 'json')- choice for return format (json, cbor)

Returns

  • JSON with timestamp or list with datetime
def vSimple(self, string=False, **kwargs):
182    def vSimple(self, string=False, **kwargs):
183        """return a datetime : middle of the TimeSlot."""
184        if string:
185            return self.value.instant.isoformat(**kwargs)
186        return self.value.instant

return a datetime : middle of the TimeSlot.

class LocationValue(observation.esvalue_base.ESValue):
193class LocationValue(ESValue):              # !!! début LocationValue
194    # %% loc
195    """
196    This class represent the Location of an Observation (point, polygon).
197
198    *Attributes (for @property see methods)* :
199
200    - **value** : Shapely object (point, polygon)
201    - **name** : String
202
203    The methods defined in this class are :
204
205    *constructor (@classmethod)*
206
207    - `LocationValue.Simple`   (point)
208    - `LocationValue.Box`
209    - `LocationValue.from_obj` (see  `ESValue.from_obj`)
210
211    *getters (@property)*
212
213    - `LocationValue.coords`
214    - `LocationValue.coorInv`
215
216    *getters*
217
218    - `LocationValue.getPoint`
219    - `LocationValue.vSimple`
220    - `LocationValue.vPointInv`
221    - `LocationValue.vPointX`
222    - `LocationValue.vPointY`
223    - `LocationValue.vCodePlus`
224    - `LocationValue.link`
225    """
226    @classmethod
227    def Simple(cls, coord):
228        '''return LocationValue built with tuple or list coordinates (x,y)'''
229        return cls(shape=shapely.geometry.Point(*coord), name='point')
230
231    @classmethod
232    def Box(cls, bounds, ccw=True):
233        '''return LocationValue built with tuple or list box coordinates (minx, miny, maxx, maxy)'''
234        if isinstance(bounds, cls):
235            bound = bounds.bounds
236        else:
237            bound = bounds
238        return cls(val=shapely.geometry.box(*bound, ccw), name='box')
239
240    @classmethod
241    def from_obj(cls, bs):
242        ''' ESValue function (see ESValue.from_obj)'''
243        return ESValue.from_obj(bs, ES.loc_clsName, simple=False)
244
245    def __init__(self, val=ES.nullCoor, name=ES.nullName):
246        '''
247        LocationValue constructor.
248
249        *Parameters*
250
251        - **val** :  compatible shapely.geometry.Point (or Polygon) Value (default nullCoor)
252        - **name** :  string (default nullName)
253        '''
254        ESValue.__init__(self)
255        if isinstance(val, self.__class__):
256            self.name = val.name
257            self.value = val.value
258            return
259        if isinstance(val, (shapely.geometry.multipoint.MultiPoint,
260                            shapely.geometry.point.Point,
261                            shapely.geometry.polygon.Polygon,
262                            shapely.geometry.multipolygon.MultiPolygon)):
263            self.value = val
264        elif not val is None:
265            if isinstance(val, str) and not name:
266                name = val
267            else:
268                self.value = self._gshape(val)
269        if self.name == ES.nullName and isinstance(name, str) and name != ES.nullName:
270            self.name = name
271
272    def __lt__(self, other):
273        ''' return minimal distance between a fixed point'''
274        if self.__class__.__name__ != other.__class__.__name__:
275            return hash(self) < hash(other)
276        # if self.coorInv == ES.nullCoor:
277        if self.coorInv == other.coorInv:
278            return self.name < other.name
279        return distance.distance(self.coorInv, ES.distRef) <  \
280            distance.distance(other.coorInv, ES.distRef)
281
282    @property
283    def __geo_interface__(self):
284        return json.loads(json.dumps(self.value.__geo_interface__, cls=ESValueEncoder))
285
286    @staticmethod
287    def boundingBox(listValue):
288        ''' return a tuple (xmin, ymin, xmax, ymax) with bounds values'''
289        return [min([val.value.bounds[0] for val in listValue]),
290                min([val.value.bounds[1] for val in listValue]),
291                max([val.value.bounds[2] for val in listValue]),
292                max([val.value.bounds[3] for val in listValue])]
293
294    @property
295    def coords(self):
296        ''' return geoJson coordinates (list)'''
297        if isinstance(self.value, shapely.geometry.polygon.Polygon):
298            coords = [list(self.value.exterior.coords)]
299        elif isinstance(self.value, shapely.geometry.point.Point):
300            coords = list(self.value.coords[0])
301        elif isinstance(self.value, shapely.geometry.linestring.LineString):
302            coords = list(self.value.coords)
303        else:
304            coords = ES.nullCoor
305        return json.loads(json.dumps(coords, cls=ESValueEncoder))
306
307    @property
308    def coorInv(self):
309        '''list (@property) : vSimple inverse coordinates [vSimple[1], vSimple[0]]'''
310        return [self.vSimple()[1], self.vSimple()[0]]
311
312    def getPoint(self):
313        ''' return a list with point coordinates [x, y] if the shape is a point, else none'''
314        if isinstance(self.value, shapely.geometry.point.Point):
315            return [self.value.x, self.value.y]
316        return None
317
318    def link(self, other):
319        '''
320        return the link (string) between self.value and other.value :
321        - equals     : if self and other are the same
322        - disjoint   : if self's shape and other's shape are disjoint
323        - within     : if other's shape contains self's shape
324        - contains   : if self's shape contains other's shape
325        - intersects : in the others cases'''
326        if self.isEqual(other, name=False):
327            return 'equals'
328        if self.value.equals(other.value):
329            return 'equals'
330        if self.value.contains(other.value):
331            return 'contains'
332        if self.value.within(other.value):
333            return 'within'
334        if self.value.disjoint(other.value):
335            return 'disjoint'
336        if self.value.intersects(other.value):
337            return 'intersects'
338
339    @staticmethod
340    def nullValue():
341        ''' return nullPosition value'''
342        return LocationValue._gshape(ES.nullCoor)
343
344    def vCodePlus(self):
345        ''' return CodePlus value (string) of the point property value'''
346        return openlocationcode.encode(self.vSimple(False)[1], self.vSimple(False)[0])
347
348    def vSimple(self, string=False):
349        ''' return simple value (centroid coordinates for the shape : 
350            [x, y]) in a string format or in a object format'''
351        if string:
352            return json.dumps([round(self.value.centroid.x, 5), round(self.value.centroid.y, 5)], cls=ESValueEncoder)
353        return [round(self.value.centroid.x, 5), round(self.value.centroid.y, 5)]
354
355    def vPointInv(self, string=False):
356        ''' return point (property) with inversed vSimple coordinates in a string format or
357        in a list format [y, x]'''
358        if string:
359            return json.dumps([self.vSimple()[1], self.vSimple()[0]], cls=ESValueEncoder)
360        return [self.vSimple()[1], self.vSimple()[0]]
361
362    def vPointX(self):
363        ''' return point (property) coordinates x '''
364        return self.vSimple()[0]
365
366    def vPointY(self):
367        ''' return point (property) coordinates y '''
368        return self.vSimple()[1]
369
370    def _jsonValue(self, **kwargs):
371        ''' return geoJson coordinates'''
372        if 'geojson' in kwargs and kwargs['geojson']:
373            return self.__geo_interface__
374        return self.coords
375
376    @staticmethod
377    def _gshape(coord):
378        ''' transform a GeoJSON coordinates (list) into a shapely geometry'''
379        if isinstance(coord, tuple):
380            coor = json.dumps(list(coord), cls=ESValueEncoder)
381        elif isinstance(coord, list):
382            coor = json.dumps(coord, cls=ESValueEncoder)
383        elif isinstance(coord, dict):
384            coor = json.dumps(coord, cls=ESValueEncoder)
385        elif isinstance(coord, str):
386            coor = coord
387        else:
388            coor = copy(coord)
389        for tpe in ["Point", "MultiPoint", "Polygon", "MultiPolygon"]:
390            try:
391                return shapely.geometry.shape(geojson.loads('{"type":"' + tpe + '","coordinates":' + coor + '}'))
392            except:
393                pass
394        raise ESValueError('coordinates unconsistent')
395        return None

This class represent the Location of an Observation (point, polygon).

Attributes (for @property see methods) :

  • value : Shapely object (point, polygon)
  • name : String

The methods defined in this class are :

constructor (@classmethod)

getters (@property)

getters

LocationValue(val=[-1, -1], name='')
245    def __init__(self, val=ES.nullCoor, name=ES.nullName):
246        '''
247        LocationValue constructor.
248
249        *Parameters*
250
251        - **val** :  compatible shapely.geometry.Point (or Polygon) Value (default nullCoor)
252        - **name** :  string (default nullName)
253        '''
254        ESValue.__init__(self)
255        if isinstance(val, self.__class__):
256            self.name = val.name
257            self.value = val.value
258            return
259        if isinstance(val, (shapely.geometry.multipoint.MultiPoint,
260                            shapely.geometry.point.Point,
261                            shapely.geometry.polygon.Polygon,
262                            shapely.geometry.multipolygon.MultiPolygon)):
263            self.value = val
264        elif not val is None:
265            if isinstance(val, str) and not name:
266                name = val
267            else:
268                self.value = self._gshape(val)
269        if self.name == ES.nullName and isinstance(name, str) and name != ES.nullName:
270            self.name = name

LocationValue constructor.

Parameters

  • val : compatible shapely.geometry.Point (or Polygon) Value (default nullCoor)
  • name : string (default nullName)
@classmethod
def Simple(cls, coord):
226    @classmethod
227    def Simple(cls, coord):
228        '''return LocationValue built with tuple or list coordinates (x,y)'''
229        return cls(shape=shapely.geometry.Point(*coord), name='point')

return LocationValue built with tuple or list coordinates (x,y)

@classmethod
def Box(cls, bounds, ccw=True):
231    @classmethod
232    def Box(cls, bounds, ccw=True):
233        '''return LocationValue built with tuple or list box coordinates (minx, miny, maxx, maxy)'''
234        if isinstance(bounds, cls):
235            bound = bounds.bounds
236        else:
237            bound = bounds
238        return cls(val=shapely.geometry.box(*bound, ccw), name='box')

return LocationValue built with tuple or list box coordinates (minx, miny, maxx, maxy)

@classmethod
def from_obj(cls, bs):
240    @classmethod
241    def from_obj(cls, bs):
242        ''' ESValue function (see ESValue.from_obj)'''
243        return ESValue.from_obj(bs, ES.loc_clsName, simple=False)

ESValue function (see ESValue.from_obj)

@staticmethod
def boundingBox(listValue):
286    @staticmethod
287    def boundingBox(listValue):
288        ''' return a tuple (xmin, ymin, xmax, ymax) with bounds values'''
289        return [min([val.value.bounds[0] for val in listValue]),
290                min([val.value.bounds[1] for val in listValue]),
291                max([val.value.bounds[2] for val in listValue]),
292                max([val.value.bounds[3] for val in listValue])]

return a tuple (xmin, ymin, xmax, ymax) with bounds values

coords

return geoJson coordinates (list)

coorInv

list (@property) : vSimple inverse coordinates [vSimple[1], vSimple[0]]

def getPoint(self):
312    def getPoint(self):
313        ''' return a list with point coordinates [x, y] if the shape is a point, else none'''
314        if isinstance(self.value, shapely.geometry.point.Point):
315            return [self.value.x, self.value.y]
316        return None

return a list with point coordinates [x, y] if the shape is a point, else none

@staticmethod
def nullValue():
339    @staticmethod
340    def nullValue():
341        ''' return nullPosition value'''
342        return LocationValue._gshape(ES.nullCoor)

return nullPosition value

def vCodePlus(self):
344    def vCodePlus(self):
345        ''' return CodePlus value (string) of the point property value'''
346        return openlocationcode.encode(self.vSimple(False)[1], self.vSimple(False)[0])

return CodePlus value (string) of the point property value

def vSimple(self, string=False):
348    def vSimple(self, string=False):
349        ''' return simple value (centroid coordinates for the shape : 
350            [x, y]) in a string format or in a object format'''
351        if string:
352            return json.dumps([round(self.value.centroid.x, 5), round(self.value.centroid.y, 5)], cls=ESValueEncoder)
353        return [round(self.value.centroid.x, 5), round(self.value.centroid.y, 5)]

return simple value (centroid coordinates for the shape : [x, y]) in a string format or in a object format

def vPointInv(self, string=False):
355    def vPointInv(self, string=False):
356        ''' return point (property) with inversed vSimple coordinates in a string format or
357        in a list format [y, x]'''
358        if string:
359            return json.dumps([self.vSimple()[1], self.vSimple()[0]], cls=ESValueEncoder)
360        return [self.vSimple()[1], self.vSimple()[0]]

return point (property) with inversed vSimple coordinates in a string format or in a list format [y, x]

def vPointX(self):
362    def vPointX(self):
363        ''' return point (property) coordinates x '''
364        return self.vSimple()[0]

return point (property) coordinates x

def vPointY(self):
366    def vPointY(self):
367        ''' return point (property) coordinates y '''
368        return self.vSimple()[1]

return point (property) coordinates y

class PropertyValue(observation.esvalue_base.ESValue):
398class PropertyValue(ESValue):              # !!! début ESValue
399    # %% prp
400    """
401    This class represents the Property of an Observation.
402
403    *Attributes (for @property see methods)* :
404
405    - **value** : dict
406    - **name** : String
407
408    The methods defined in this class are :
409
410    *constructor (@classmethod)*
411
412    - `PropertyValue.Simple`   (property type)
413    - `PropertyValue.Box`      (set of property type)
414    - `PropertyValue.from_obj` (see  `ESValue.from_obj`)
415
416    *getters*
417
418    - `PropertyValue.vSimple`
419    - `PropertyValue.link`
420    """
421    @classmethod
422    def Simple(cls, prp, name='simple', prp_dict=False):
423        '''PropertyValue built with a value (property type) '''
424        return cls(val={ES.prp_type: prp}, name=name, prp_dict=prp_dict)
425
426    @classmethod
427    def Box(cls, prp, name='box', prp_dict=False):
428        '''PropertyValue built with a value (property type) '''
429        return cls(val={ES.prp_type: prp}, name=name, prp_dict=prp_dict)
430
431    @classmethod
432    def from_obj(cls, bs):
433        ''' ESValue function (see ESValue.from_obj)'''
434        return ESValue.from_obj(bs, ES.prp_clsName, simple=False)
435
436    def __init__(self, val=ES.nullPrp, name=ES.nullName, prp_dict=False):
437        '''
438        PropertyValue constructor.
439
440        *Parameters*
441
442        - **val** :  property dict or json string (default nullPrp)
443        - **name** :  string (default nullName)
444        - **prp_dict** : boolean(default False) - if True type property has to be in the type dictionary
445        '''
446        ESValue.__init__(self)
447        if isinstance(val, self.__class__):
448            self.name = val.name
449            self.value = val.value
450            return
451        if not val is None and name == ES.prp_type:
452            name = None
453            val = {ES.prp_type: val}
454        elif isinstance(val, str) and isinstance(name, str) and name != ES.nullName:
455            val = {name: val}
456        if isinstance(val, dict):
457            if len(val) > 0 and isinstance(list(val.values())[0], dict):
458                self.name = list(val.keys())[0]
459                self.value |= val[list(val.keys())[0]]
460            else:
461                self.value |= val
462        elif isinstance(val, str):
463            name = val
464        # elif not val is None: raise ESValueError('type data not compatible with PropertyValue')
465        # else: raise ESValueError('type data not compatible with PropertyValue')
466
467        if self.name == ES.nullName and isinstance(name, str) and name != ES.nullName:
468            self.name = name
469        if not ES.prp_type in self.value:
470            raise ESValueError("type property not defined")
471        if not isinstance(self.value[ES.prp_type], list):
472            if prp_dict and not self.value[ES.prp_type] in ES.prop:
473                raise ESValueError(
474                    "property not present in standard dictionnary")
475            if prp_dict:
476                self.value[ES.prp_unit] = ES.prop[self.value[ES.prp_type]][5]
477
478    def __lt__(self, other):
479        """lower if string simple value + name is lower"""
480        if self.__class__.__name__ != other.__class__.name:
481            return hash(self) < hash(other)
482        return self.simple + self.name < other.simple + other.name
483
484    @staticmethod
485    def boundingBox(listValue):
486        ''' return a tuple with 'prp' values'''
487        return [val.value['prp'] for val in listValue]
488
489    def link(self, other):
490        '''
491        return the link (string) between self.value and other.value :
492        - equals     : if self and other are the same
493        - disjoint   : if the self's key/val are all different from other's key/val
494        - within     : if all self's key/val are included in other's key/val
495        - contains   : if all other's key/val are included in self's key/val
496        - intersects : in the others cases'''
497        if self.isEqual(other, name=False):
498            return 'equals'
499        sprp = self._setprp(self.value[ES.prp_type])
500        oprp = self._setprp(other.value[ES.prp_type])
501        if oprp == sprp:
502            union = other.value | self.value
503            union2 = self.value | other.value
504            if union == self.value and union2 == self.value:
505                return 'within'
506            if union == other.value and union2 == other.value:
507                return 'contains'
508            if union == union2:
509                return 'disjoint'
510            return 'intersects'
511        if sprp == sprp | oprp:
512            return 'contains'
513        if oprp == sprp | oprp:
514            return 'within'
515        if oprp & sprp == set():
516            return 'disjoint'
517        else:
518            return 'intersects'
519        return 'undefined'
520
521    @staticmethod
522    def nullValue():
523        ''' return nullPrp value'''
524        return {ES.prp_type: ES.nullDict, ES.prp_unit: ES.prop[ES.nullDict][5]}
525
526    def vSimple(self, string=False):
527        ''' return simple value (type for the property) in a string format or in a object format'''
528        simple = ES.nullDict
529        if ES.prp_type in self.value:
530            simple = self.value[ES.prp_type]
531        if string:
532            return json.dumps(simple, cls=ESValueEncoder)
533        return simple
534
535    def _jsonValue(self, **kwargs):
536        option = {'encoded': False} | kwargs
537        li = {}
538        for k, v in self.value.items():
539            if k in [ES.prp_type, ES.prp_unit, ES.prp_sampling, ES.prp_appli, ES.prp_EMFId]:
540                if v != ES.nullDict:
541                    li[k] = v
542            elif k in [ES.prp_period, ES.prp_interval, ES.prp_uncertain]:
543                if v != ES.nullInt:
544                    li[k] = v
545            else:
546                li[k] = v
547        if option['encoded']:
548            return json.dumps(li, ensure_ascii=False, cls=ESValueEncoder)
549        return li
550
551    @staticmethod
552    def _setprp(val):
553        if isinstance(val, list):
554            return set(val)
555        return {val}

This class represents the Property of an Observation.

Attributes (for @property see methods) :

  • value : dict
  • name : String

The methods defined in this class are :

constructor (@classmethod)

getters

PropertyValue(val={'prp': '-'}, name='', prp_dict=False)
436    def __init__(self, val=ES.nullPrp, name=ES.nullName, prp_dict=False):
437        '''
438        PropertyValue constructor.
439
440        *Parameters*
441
442        - **val** :  property dict or json string (default nullPrp)
443        - **name** :  string (default nullName)
444        - **prp_dict** : boolean(default False) - if True type property has to be in the type dictionary
445        '''
446        ESValue.__init__(self)
447        if isinstance(val, self.__class__):
448            self.name = val.name
449            self.value = val.value
450            return
451        if not val is None and name == ES.prp_type:
452            name = None
453            val = {ES.prp_type: val}
454        elif isinstance(val, str) and isinstance(name, str) and name != ES.nullName:
455            val = {name: val}
456        if isinstance(val, dict):
457            if len(val) > 0 and isinstance(list(val.values())[0], dict):
458                self.name = list(val.keys())[0]
459                self.value |= val[list(val.keys())[0]]
460            else:
461                self.value |= val
462        elif isinstance(val, str):
463            name = val
464        # elif not val is None: raise ESValueError('type data not compatible with PropertyValue')
465        # else: raise ESValueError('type data not compatible with PropertyValue')
466
467        if self.name == ES.nullName and isinstance(name, str) and name != ES.nullName:
468            self.name = name
469        if not ES.prp_type in self.value:
470            raise ESValueError("type property not defined")
471        if not isinstance(self.value[ES.prp_type], list):
472            if prp_dict and not self.value[ES.prp_type] in ES.prop:
473                raise ESValueError(
474                    "property not present in standard dictionnary")
475            if prp_dict:
476                self.value[ES.prp_unit] = ES.prop[self.value[ES.prp_type]][5]

PropertyValue constructor.

Parameters

  • val : property dict or json string (default nullPrp)
  • name : string (default nullName)
  • prp_dict : boolean(default False) - if True type property has to be in the type dictionary
@classmethod
def Simple(cls, prp, name='simple', prp_dict=False):
421    @classmethod
422    def Simple(cls, prp, name='simple', prp_dict=False):
423        '''PropertyValue built with a value (property type) '''
424        return cls(val={ES.prp_type: prp}, name=name, prp_dict=prp_dict)

PropertyValue built with a value (property type)

@classmethod
def Box(cls, prp, name='box', prp_dict=False):
426    @classmethod
427    def Box(cls, prp, name='box', prp_dict=False):
428        '''PropertyValue built with a value (property type) '''
429        return cls(val={ES.prp_type: prp}, name=name, prp_dict=prp_dict)

PropertyValue built with a value (property type)

@classmethod
def from_obj(cls, bs):
431    @classmethod
432    def from_obj(cls, bs):
433        ''' ESValue function (see ESValue.from_obj)'''
434        return ESValue.from_obj(bs, ES.prp_clsName, simple=False)

ESValue function (see ESValue.from_obj)

@staticmethod
def boundingBox(listValue):
484    @staticmethod
485    def boundingBox(listValue):
486        ''' return a tuple with 'prp' values'''
487        return [val.value['prp'] for val in listValue]

return a tuple with 'prp' values

@staticmethod
def nullValue():
521    @staticmethod
522    def nullValue():
523        ''' return nullPrp value'''
524        return {ES.prp_type: ES.nullDict, ES.prp_unit: ES.prop[ES.nullDict][5]}

return nullPrp value

def vSimple(self, string=False):
526    def vSimple(self, string=False):
527        ''' return simple value (type for the property) in a string format or in a object format'''
528        simple = ES.nullDict
529        if ES.prp_type in self.value:
530            simple = self.value[ES.prp_type]
531        if string:
532            return json.dumps(simple, cls=ESValueEncoder)
533        return simple

return simple value (type for the property) in a string format or in a object format

class NamedValue(observation.esvalue_base.ESValue):
558class NamedValue (ESValue):               # !!! début ResValue
559    # %% nam
560    '''This class represent a simple value with an associated string.
561
562    *Attributes (for @property see methods)* :
563
564    - **value** : any json object
565    - **name** : String
566
567    The methods defined in this class are :
568
569    *constructor*
570
571    - `NamedValue.from_obj` (see  `ESValue.from_obj`)
572
573    *getters*
574
575    - `NamedValue.vSimple`
576    '''
577    @classmethod
578    def from_obj(cls, bs):
579        ''' ESValue function (see ESValue.from_obj)'''
580        return ESValue.from_obj(bs, ES.nam_clsName, simple=False)
581
582    def __init__(self, val=ES.nullVal, name=ES.nullName):
583        '''
584        NamedValue constructor.
585
586        *Parameters*
587
588        - **val** :  any simple object (default nullVal)
589        - **name** : string (default nullName)
590        '''
591        ESValue.__init__(self)
592        if isinstance(val, self.__class__):
593            self.name = val.name
594            self.value = val.value
595            return
596        self.value = ESValue._castsimple(val)
597        if self.name == ES.nullName and isinstance(name, str) and name != ES.nullName:
598            self.name = name
599
600    @staticmethod
601    def nullValue():
602        ''' return nullVal value'''
603        return ES.nullVal
604
605    def vSimple(self, string=False):
606        '''return float value in string or object format'''
607        from util import util
608        if string:
609            return str(util.cast(self.value, dtype='simple'))
610        return util.cast(self.value, dtype='simple')
611
612    def _jsonValue(self, **option):
613        '''return the value '''
614        if isinstance(self.value, (int, str, float, bool, list, dict,
615                                   datetime.datetime, type(None), bytes)):
616            return self.value
617        if isinstance(self.value, tuple):
618            return list(self.value)

This class represent a simple value with an associated string.

Attributes (for @property see methods) :

  • value : any json object
  • name : String

The methods defined in this class are :

constructor

getters

NamedValue(val=nan, name='')
582    def __init__(self, val=ES.nullVal, name=ES.nullName):
583        '''
584        NamedValue constructor.
585
586        *Parameters*
587
588        - **val** :  any simple object (default nullVal)
589        - **name** : string (default nullName)
590        '''
591        ESValue.__init__(self)
592        if isinstance(val, self.__class__):
593            self.name = val.name
594            self.value = val.value
595            return
596        self.value = ESValue._castsimple(val)
597        if self.name == ES.nullName and isinstance(name, str) and name != ES.nullName:
598            self.name = name

NamedValue constructor.

Parameters

  • val : any simple object (default nullVal)
  • name : string (default nullName)
@classmethod
def from_obj(cls, bs):
577    @classmethod
578    def from_obj(cls, bs):
579        ''' ESValue function (see ESValue.from_obj)'''
580        return ESValue.from_obj(bs, ES.nam_clsName, simple=False)

ESValue function (see ESValue.from_obj)

value
@staticmethod
def nullValue():
600    @staticmethod
601    def nullValue():
602        ''' return nullVal value'''
603        return ES.nullVal

return nullVal value

def vSimple(self, string=False):
605    def vSimple(self, string=False):
606        '''return float value in string or object format'''
607        from util import util
608        if string:
609            return str(util.cast(self.value, dtype='simple'))
610        return util.cast(self.value, dtype='simple')

return float value in string or object format

class ExternValue(observation.esvalue_base.ESValue):
621class ExternValue (ESValue):               # !!! début ResValue
622    # %% ext
623    '''This class represent a complex (extern) value with an associated string.
624
625    *Attributes (for @property see methods)* :
626
627    - **value** : any object
628    - **name** : String
629
630    The methods defined in this class are :
631
632    *constructor*
633
634    - `ExternValue.from_obj` (see  `ESValue.from_obj`)
635
636    *getters*
637
638    - `ExternValue.vSimple`
639    '''
640    @classmethod
641    def from_obj(cls, bs):
642        ''' ESValue function (see ESValue.from_obj)'''
643        return ESValue.from_obj(bs, ES.ext_clsName, simple=False)
644
645    def __init__(self, val=ES.nullExternVal, name=ES.nullName, className=None):
646        '''
647        ExternValue constructor.
648
649        *Parameters*
650
651        - **val** :  any simple object (default nullVal)
652        - **name** : string (default nullName)
653
654        '''
655        ESValue.__init__(self)
656        if isinstance(val, self.__class__):
657            self.name = val.name
658            self.value = val.value
659            return
660        #self.value = ESValue.from_obj(val, classname=className)
661        if val == ES.nullExternVal and name == ES.nullName:
662            return
663        if not className:
664            className = val.__class__.__name__
665        if className in _classval():
666            self.value = _classval()[className](val)
667        else:
668            raise ESValueError('class name inconsistent with ExternValue')
669        if self.name == ES.nullName and isinstance(name, str) and name != ES.nullName:
670            self.name = name
671
672    @staticmethod
673    def nullValue():
674        ''' return nullVal value'''
675        return ES.nullExternVal
676
677    def vSimple(self, string=False):
678        '''return conversion from value to float'''
679        from util import util
680        if string:
681            return str(util.cast(self.value, dtype='simple'))
682        return util.cast(self.value, dtype='simple')
683
684    def _jsonValue(self, **option):
685        '''return a json object for the value '''
686        if self.value.__class__.__name__ in ['Field', 'Dataset', 'Observation']:
687            return self.value.json(encoded=False, encode_format='json')
688        if isinstance(self.value, (int, str, float, bool, list, tuple, dict, datetime.datetime, type(None), bytes)):
689            return self.value
690        if isinstance(self.value, (DatationValue, LocationValue, PropertyValue, NamedValue, ExternValue)):
691            return self.value.json(encoded=False, encode_format='json')
692        try:
693            return self.value.to_json(encoded=False, encode_format='json',
694                                      json_info=False, json_res_index=True, json_param=True)
695        except:
696            return object.__repr__(self.value)

This class represent a complex (extern) value with an associated string.

Attributes (for @property see methods) :

  • value : any object
  • name : String

The methods defined in this class are :

constructor

getters

ExternValue(val=None, name='', className=None)
645    def __init__(self, val=ES.nullExternVal, name=ES.nullName, className=None):
646        '''
647        ExternValue constructor.
648
649        *Parameters*
650
651        - **val** :  any simple object (default nullVal)
652        - **name** : string (default nullName)
653
654        '''
655        ESValue.__init__(self)
656        if isinstance(val, self.__class__):
657            self.name = val.name
658            self.value = val.value
659            return
660        #self.value = ESValue.from_obj(val, classname=className)
661        if val == ES.nullExternVal and name == ES.nullName:
662            return
663        if not className:
664            className = val.__class__.__name__
665        if className in _classval():
666            self.value = _classval()[className](val)
667        else:
668            raise ESValueError('class name inconsistent with ExternValue')
669        if self.name == ES.nullName and isinstance(name, str) and name != ES.nullName:
670            self.name = name

ExternValue constructor.

Parameters

  • val : any simple object (default nullVal)
  • name : string (default nullName)
@classmethod
def from_obj(cls, bs):
640    @classmethod
641    def from_obj(cls, bs):
642        ''' ESValue function (see ESValue.from_obj)'''
643        return ESValue.from_obj(bs, ES.ext_clsName, simple=False)

ESValue function (see ESValue.from_obj)

@staticmethod
def nullValue():
672    @staticmethod
673    def nullValue():
674        ''' return nullVal value'''
675        return ES.nullExternVal

return nullVal value

def vSimple(self, string=False):
677    def vSimple(self, string=False):
678        '''return conversion from value to float'''
679        from util import util
680        if string:
681            return str(util.cast(self.value, dtype='simple'))
682        return util.cast(self.value, dtype='simple')

return conversion from value to float

class ESValueError(builtins.Exception):
699class ESValueError(Exception):
700    # %% ES except
701    ''' ESValue Exception'''
702    pass

ESValue Exception

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args