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 :
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
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)
DatationValue.Simple
(instant)DatationValue.Box
(interval)DatationValue.from_obj
(seeESValue.from_obj
)
getters
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)
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)
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)
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)
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
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
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
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]
return the link (string) between self.value and other.value :
- equals : if self and other are the same
- disjoint : if self's intervals and other's intervals are all disjoint
- within : if all self's intervals are included in other's intervals
- contains : if all other's intervals are included in self's intervals
- intersects : in the others cases
164 @staticmethod 165 def nullValue(): 166 ''' return nullDate value''' 167 return TimeSlot(ES.nullDate)
return nullDate value
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
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)
LocationValue.Simple
(point)LocationValue.Box
LocationValue.from_obj
(seeESValue.from_obj
)
getters (@property)
getters
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)
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)
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)
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)
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
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
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'
return the link (string) between self.value and other.value :
- equals : if self and other are the same
- disjoint : if self's shape and other's shape are disjoint
- within : if other's shape contains self's shape
- contains : if self's shape contains other's shape
- intersects : in the others cases
339 @staticmethod 340 def nullValue(): 341 ''' return nullPosition value''' 342 return LocationValue._gshape(ES.nullCoor)
return nullPosition value
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
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
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]
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)
PropertyValue.Simple
(property type)PropertyValue.Box
(set of property type)PropertyValue.from_obj
(seeESValue.from_obj
)
getters
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
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)
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)
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)
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
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'
return the link (string) between self.value and other.value :
- equals : if self and other are the same
- disjoint : if the self's key/val are all different from other's key/val
- within : if all self's key/val are included in other's key/val
- contains : if all other's key/val are included in self's key/val
- intersects : in the others cases
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
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
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
NamedValue.from_obj
(seeESValue.from_obj
)
getters
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)
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)
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
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
ExternValue.from_obj
(seeESValue.from_obj
)
getters
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)
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)
ESValue Exception
Inherited Members
- builtins.Exception
- Exception
- builtins.BaseException
- with_traceback
- args