ntv-numpy.ntv_numpy.xdataset
@author: Philippe@loco-labs.io
The xdataset
module is part of the ntv-numpy.ntv_numpy
package (specification document).
It contains the classes Xdataset
, XdatasetInterface
, XdatasetCategory
for
the multidimensional dataset.
For more information, see the user guide or the github repository.
1# -*- coding: utf-8 -*- 2""" 3@author: Philippe@loco-labs.io 4 5The `xdataset` module is part of the `ntv-numpy.ntv_numpy` package ([specification document]( 6https://loco-philippe.github.io/ES/JSON%20semantic%20format%20(JSON-NTV).htm)). 7 8It contains the classes `Xdataset`, `XdatasetInterface`, `XdatasetCategory` for 9the multidimensional dataset. 10 11For more information, see the 12[user guide](https://loco-philippe.github.io/ntv-numpy/docs/user_guide.html) 13 or the [github repository](https://github.com/loco-philippe/ntv-numpy). 14""" 15from abc import ABC, abstractmethod 16import json 17import pprint 18from json_ntv import Ntv 19from ntv_numpy.ndarray import Nutil 20from ntv_numpy.xndarray import Xndarray 21from ntv_numpy.xconnector import XarrayConnec, ScippConnec, AstropyNDDataConnec 22from ntv_numpy.xconnector import PandasConnec 23 24 25class XdatasetCategory(ABC): 26 ''' category of Xndarray (dynamic tuple of full_name) - see Xdataset docstring''' 27 28 xnd: list = NotImplemented 29 names: list = NotImplemented 30 31 @abstractmethod 32 def dims(self, var, json_name=False): 33 '''method defined in Xdataset class''' 34 35 @property 36 def data_arrays(self): 37 '''return a tuple of data_arrays Xndarray full_name''' 38 return tuple(sorted(nda for nda in self.namedarrays 39 if not nda in self.dimensions + self.uniques)) 40 41 @property 42 def dimensions(self): 43 '''return a tuple of dimensions Xndarray full_name''' 44 dimable = [] 45 for var in self.variables: 46 dimable += self.dims(var) 47 return tuple(sorted(set(nda for nda in dimable if nda in self.namedarrays))) 48 49 @property 50 def shape(self): 51 '''return an array with the length of dimensions''' 52 return [len(self[dim]) for dim in self.dimensions] 53 54 @property 55 def coordinates(self): 56 '''return a tuple of coordinates Xndarray full_name''' 57 dims = set(self.dimensions) 58 if not dims: 59 return () 60 return tuple(sorted(set(xnda.name for xnda in self.xnd 61 if xnda.xtype == 'variable' and set(xnda.links) != dims))) 62 63 @property 64 def data_vars(self): 65 '''return a tuple of data_vars Xndarray full_name''' 66 dims = set(self.dimensions) 67 if not dims: 68 return self.variables 69 return tuple(sorted(xnda.name for xnda in self.xnd 70 if xnda.xtype == 'variable' and set(xnda.links) == dims)) 71 72 @property 73 def namedarrays(self): 74 '''return a tuple of namedarray Xndarray full_name''' 75 return tuple(sorted(xnda.name for xnda in self.xnd if xnda.xtype == 'namedarray')) 76 77 @property 78 def variables(self): 79 '''return a tuple of variables Xndarray full_name''' 80 return tuple(sorted(xnda.name for xnda in self.xnd if xnda.xtype == 'variable')) 81 82 @property 83 def undef_vars(self): 84 '''return a tuple of variables Xndarray full_name with inconsistent shape''' 85 return tuple(sorted(var for var in self.variables if self[var].shape != 86 [len(self[dim]) for dim in self.dims(var)])) 87 88 @property 89 def undef_links(self): 90 '''return a tuple of variables Xndarray full_name with inconsistent links''' 91 return tuple(sorted(link for var in self.variables for link in self[var].links 92 if not link in self.names)) 93 94 @property 95 def masks(self): 96 '''return a tuple of additional Xndarray full_name with boolean ntv_type''' 97 return tuple(sorted(xnda.full_name for xnda in self.xnd 98 if xnda.xtype == 'additional' and xnda.ntv_type == 'boolean')) 99 100 @property 101 def data_add(self): 102 '''return a tuple of additional Xndarray full_name with not boolean ntv_type''' 103 return tuple(sorted(xnda.full_name for xnda in self.xnd 104 if xnda.xtype == 'additional' and xnda.ntv_type != 'boolean')) 105 106 @property 107 def metadata(self): 108 '''return a tuple of metadata Xndarray full_name''' 109 return tuple(sorted(xnda.full_name for xnda in self.xnd if xnda.xtype == 'meta')) 110 111 @property 112 def uniques(self): 113 '''return a tuple of unique Xndarray full_name''' 114 return tuple(full_name for full_name in self.namedarrays if len(self[full_name]) == 1) 115 116 @property 117 def additionals(self): 118 '''return a tuple of additionals Xndarray full_name''' 119 return tuple(sorted(xnda.full_name for xnda in self.xnd if xnda.xtype == 'additional')) 120 121 def group(self, grp): 122 '''return a tuple of Xndarray full_name with the same name''' 123 if isinstance(grp, str): 124 return tuple(sorted(xnda.full_name for xnda in self.xnd 125 if grp in (xnda.name, xnda.full_name))) 126 return tuple(sorted(nam for gr_nam in grp for nam in self.group(gr_nam))) 127 128 def add_group(self, add_name): 129 '''return a tuple of Xndarray full_name with the same add_name''' 130 return tuple(sorted(xnda.full_name for xnda in self.xnd if xnda.add_name == add_name)) 131 132 133class XdatasetInterface(ABC): 134 ''' Xdataset interface - see Xdataset docstring''' 135 136 name: str = NotImplemented 137 xnd: list = NotImplemented 138 139 @staticmethod 140 def read_json(jsn, **kwargs): 141 ''' convert json data into a Xdataset. 142 143 *Parameters* 144 145 - **convert** : boolean (default True) - If True, convert json data with 146 non Numpy ntv_type into Xndarray with python type 147 ''' 148 option = {'convert': True} | kwargs 149 jso = json.loads(jsn) if isinstance(jsn, str) else jsn 150 value, name = Ntv.decode_json(jso)[:2] 151 152 xnd = [Xndarray.read_json({key: val}, **option) 153 for key, val in value.items()] 154 return Xdataset(xnd, name) 155 156 def to_json(self, **kwargs): 157 ''' convert a Xdataset into json-value. 158 159 *Parameters* 160 161 - **encoded** : Boolean (default False) - json value if False else json text 162 - **header** : Boolean (default True) - including 'xdataset' type 163 - **notype** : list of Boolean (default list of None) - including data type if False 164 - **novalue** : Boolean (default False) - including value if False 165 - **noshape** : Boolean (default True) - if True, without shape if dim < 1 166 - **format** : list of string (default list of 'full') - representation 167 format of the ndarray, 168 ''' 169 notype = kwargs['notype'] if ('notype' in kwargs and isinstance(kwargs['notype'], list) and 170 len(kwargs['notype']) == len(self)) else [False] * len(self) 171 forma = kwargs['format'] if ('format' in kwargs and isinstance(kwargs['format'], list) and 172 len(kwargs['format']) == len(self)) else ['full'] * len(self) 173 noshape = kwargs.get('noshape', True) 174 dic_xnd = {} 175 for xna, notyp, forma in zip(self.xnd, notype, forma): 176 dic_xnd |= xna.to_json(notype=notyp, novalue=kwargs.get('novalue', False), 177 noshape=noshape, format=forma, header=False) 178 return Nutil.json_ntv(self.name, 'xdataset', dic_xnd, 179 header=kwargs.get('header', True), 180 encoded=kwargs.get('encoded', False)) 181 182 def to_xarray(self, **kwargs): 183 '''return a DataArray or a Dataset from a Xdataset 184 185 *Parameters* 186 187 - **dataset** : Boolean (default True) - if False and a single data_var, return a DataArray 188 ''' 189 return XarrayConnec.xexport(self, **kwargs) 190 191 @staticmethod 192 def from_xarray(xar, **kwargs): 193 '''return a Xdataset from a DataArray or a Dataset''' 194 return XarrayConnec.ximport(xar, Xdataset, **kwargs) 195 196 def to_scipp(self, **kwargs): 197 '''return a sc.DataArray or a sc.Dataset from a Xdataset 198 199 *Parameters* 200 201 - **dataset** : Boolean (default True) - if False and a single data_var, 202 return a DataArray 203 - **datagroup** : Boolean (default True) - if True return a DataGroup with 204 metadata and data_arrays 205 - **ntv_type** : Boolean (default True) - if True add ntv-type to the name 206 ''' 207 return ScippConnec.xexport(self, **kwargs) 208 209 @staticmethod 210 def from_scipp(sci, **kwargs): 211 '''return a Xdataset from a scipp object DataArray, Dataset or DataGroup''' 212 return ScippConnec.ximport(sci, Xdataset, **kwargs) 213 214 def to_nddata(self, **kwargs): 215 '''return a NDData from a Xdataset''' 216 return AstropyNDDataConnec.xexport(self, **kwargs) 217 218 @staticmethod 219 def from_nddata(ndd, **kwargs): 220 '''return a Xdataset from a NDData''' 221 return AstropyNDDataConnec.ximport(ndd, Xdataset, **kwargs) 222 223 def to_dataframe(self, **kwargs): 224 '''return a pd.DataFrame from a Xdataset''' 225 return PandasConnec.xexport(self, **kwargs) 226 227 @staticmethod 228 def from_dataframe(dfr, **kwargs): 229 '''return a Xdataset from a pd.DataFrame''' 230 return PandasConnec.ximport(dfr, Xdataset, **kwargs) 231 232 233class Xdataset(XdatasetCategory, XdatasetInterface): 234 ''' Representation of a multidimensional Dataset 235 236 *Attributes :* 237 - **name** : String - name of the Xdataset 238 - **xnd**: list of Xndarray 239 240 *dynamic values (@property)* 241 - `xtype` 242 - `validity` 243 - `dic_xnd` 244 - `partition` 245 - `length` 246 - `info` 247 248 *methods* 249 - `parent` 250 - `dims` 251 - `shape_dims` 252 - `to_canonical` 253 - `to_ndarray` 254 - `to_darray` 255 256 *XdatasetCategory (@property)* 257 - `names` 258 - `data_arrays` 259 - `dimensions` 260 - `coordinates` 261 - `data_vars` 262 - `namedarrays` 263 - `variables` 264 - `undef_vars` 265 - `undef_links` 266 - `masks` 267 - `data_add` 268 - `meta` 269 - `metadata` 270 - `uniques` 271 - `additionals` 272 - `group` 273 - `add_group` 274 275 *XdatasetInterface methods * 276 - `read_json` (static) 277 - `to_json` 278 - `from_xarray` (static) 279 - `to_xarray` 280 - `from_scipp` (static) 281 - `to_scipp` 282 - `from_nddata` (static) 283 - `to_nddata` 284 - `from_dataframe` (static) 285 - `to_dataframe` 286 ''' 287 288 def __init__(self, xnd=None, name=None): 289 '''Xdataset constructor 290 291 *Parameters* 292 293 - **xnd** : Xdataset/Xndarray/list of Xndarray (default None), 294 - **name** : String (default None) - name of the Xdataset 295 ''' 296 self.name = name 297 match xnd: 298 case list(): 299 self.xnd = xnd 300 case xdat if isinstance(xdat, Xdataset): 301 self.name = xdat.name 302 self.xnd = xdat.xnd 303 case xnda if isinstance(xnda, Xndarray): 304 self.xnd = [xnda] 305 case _: 306 self.xnd = [] 307 308 def __repr__(self): 309 '''return classname and number of value''' 310 return (self.__class__.__name__ + '[' + str(len(self)) + ']\n' + 311 pprint.pformat(self.to_json(novalue=True, header=False, noshape=False))) 312 313 def __str__(self): 314 '''return json string format''' 315 return json.dumps(self.to_json()) 316 317 def __eq__(self, other): 318 '''equal if xnd are equal''' 319 for xnda in self.xnd: 320 if not xnda in other: 321 return False 322 for xnda in other.xnd: 323 if not xnda in self: 324 return False 325 return True 326 327 def __len__(self): 328 '''number of Xndarray''' 329 return len(self.xnd) 330 331 def __contains__(self, item): 332 ''' item of xnd''' 333 return item in self.xnd 334 335 def __getitem__(self, selec): 336 ''' return Xndarray or tuple of Xndarray with selec: 337 - string : name of a xndarray, 338 - integer : index of a xndarray, 339 - index selector : index interval 340 - tuple : names or index ''' 341 if selec is None or selec == '' or selec in ([], ()): 342 return self 343 if isinstance(selec, (list, tuple)) and len(selec) == 1: 344 selec = selec[0] 345 if isinstance(selec, tuple): 346 return [self[i] for i in selec] 347 if isinstance(selec, str): 348 return self.dic_xnd[selec] 349 if isinstance(selec, list): 350 return self[selec[0]][selec[1:]] 351 return self.xnd[selec] 352 353 def __delitem__(self, ind): 354 '''remove a Xndarray (ind is index, name or tuple of names).''' 355 if isinstance(ind, int): 356 del self.xnd[ind] 357 elif isinstance(ind, str): 358 del self.xnd[self.names.index(ind)] 359 elif isinstance(ind, tuple): 360 ind_n = [self.names[i] if isinstance(i, int) else i for i in ind] 361 for i in ind_n: 362 del self[i] 363 364 def __copy__(self): 365 ''' Copy all the data ''' 366 return self.__class__(self) 367 368 def parent(self, var): 369 '''return the Xndarray parent (where the full_name is equal to the name)''' 370 if var.name in self.names: 371 return self[var.name] 372 return var 373 374 def dims(self, var, json_name=False): 375 '''return the list of parent namedarrays of the links of a Xndarray 376 377 *parameters* 378 379 - **var**: string - full_name of the Xndarray 380 - **json_name**: boolean (defaut False) - if True return json_name else full_name 381 ''' 382 if not var in self.names: 383 return None 384 if self[var].add_name and not self[var].links: 385 return self.dims(self[var].name, json_name) 386 if var in self.namedarrays: 387 return [self[var].json_name if json_name else var] 388 if not var in self.variables + self.additionals: 389 return None 390 list_dims = [] 391 for link in self[var].links: 392 list_dims += self.dims(link, json_name) if self.dims(link, 393 json_name) else [link] 394 return list_dims 395 396 def shape_dims(self, var): 397 '''return a shape with the dimensions associated to the var full_name''' 398 return [len(self[dim]) for dim in self.dims(var) 399 ] if set(self.dims(var)) <= set(self.names) else None 400 401 @property 402 def validity(self): 403 '''return the validity state: 'inconsistent', 'undifined' or 'valid' ''' 404 for xnda in self: 405 if xnda.mode in ['relative', 'inconsistent']: 406 return 'undefined' 407 if self.undef_links or self.undef_vars: 408 return 'inconsistent' 409 return 'valid' 410 411 @property 412 def xtype(self): 413 '''return the Xdataset type: 'meta', 'group', 'mono', 'multi' ''' 414 if self.metadata and not (self.additionals or self.variables or 415 self.namedarrays): 416 return 'meta' 417 if self.validity != 'valid': 418 return 'group' 419 match len(self.data_vars): 420 case 0: 421 return 'group' 422 case 1: 423 return 'mono' 424 case _: 425 return 'multi' 426 427 @property 428 def dic_xnd(self): 429 '''return a dict of Xndarray where key is the full_name''' 430 return {xnda.full_name: xnda for xnda in self.xnd} 431 432 @property 433 def length(self): 434 '''return the max length of Xndarray''' 435 return max(len(xnda) for xnda in self.xnd) 436 437 @property 438 def names(self): 439 '''return a tuple with the Xndarray full_name''' 440 return tuple(xnda.full_name for xnda in self.xnd) 441 442 @property 443 def partition(self): 444 '''return a dict of Xndarray grouped with category''' 445 dic = {} 446 dic |= {'data_vars': list(self.data_vars)} if self.data_vars else {} 447 dic |= {'data_arrays': list(self.data_arrays) 448 } if self.data_arrays else {} 449 dic |= {'dimensions': list(self.dimensions)} if self.dimensions else {} 450 dic |= {'coordinates': list(self.coordinates) 451 } if self.coordinates else {} 452 dic |= {'additionals': list(self.additionals) 453 } if self.additionals else {} 454 dic |= {'metadata': list(self.metadata)} if self.metadata else {} 455 dic |= {'uniques': list(self.uniques)} if self.uniques else {} 456 return dic 457 458 @property 459 def info(self): 460 '''return a dict with Xdataset information ''' 461 inf = {'name': self.name, 'xtype': self.xtype} | self.partition 462 inf['validity'] = self.validity 463 inf['length'] = len(self[self.data_vars[0]]) if self.data_vars else 0 464 inf['width'] = len(self) 465 data = {name: {key: val for key, val in self[name].info.items() if key != 'name'} 466 for name in self.names} 467 return {'structure': {key: val for key, val in inf.items() if val}, 468 'data': {key: val for key, val in data.items() if val}} 469 470 @property 471 def tab_info(self): 472 '''return a dict with Xdataset information for tabular interface''' 473 info = self.info 474 data = info['data'] 475 t_info = {} 476 if 'dimensions' in info['structure']: 477 t_info['dimensions'] = info['structure']['dimensions'] 478 t_info['data'] = {name: {key: val for key, val in data[name].items() 479 if key in ['shape', 'xtype', 'meta', 'links']} 480 for name in data} 481 return t_info 482 483 def to_canonical(self): 484 '''remove optional links of the included Xndarray''' 485 for name in self.names: 486 if self[name].links in ([self[name].name], [name]): 487 self[name].links = None 488 for add in self.additionals: 489 if self[add].links in [self[self[add].name].links, 490 [self[add].name]]: 491 self[add].links = None 492 for unic in self.uniques: 493 self[unic].links = None 494 return self 495 496 def to_ndarray(self, full_name): 497 '''convert a Xndarray from a Xdataset in a np.ndarray''' 498 if self.shape_dims(full_name) is None: 499 data = self[full_name].ndarray 500 else: 501 data = self[full_name].darray.reshape(self.shape_dims(full_name)) 502 if data.dtype.name[:8] == 'datetime': 503 data = data.astype('datetime64[ns]') 504 return data 505 506 def to_darray(self, full_name): 507 '''convert a Xndarray from a Xdataset in a flattened np.ndarray''' 508 data = self[full_name].darray 509 if data.dtype.name[:8] == 'datetime': 510 data = data.astype('datetime64[ns]') 511 return data
26class XdatasetCategory(ABC): 27 ''' category of Xndarray (dynamic tuple of full_name) - see Xdataset docstring''' 28 29 xnd: list = NotImplemented 30 names: list = NotImplemented 31 32 @abstractmethod 33 def dims(self, var, json_name=False): 34 '''method defined in Xdataset class''' 35 36 @property 37 def data_arrays(self): 38 '''return a tuple of data_arrays Xndarray full_name''' 39 return tuple(sorted(nda for nda in self.namedarrays 40 if not nda in self.dimensions + self.uniques)) 41 42 @property 43 def dimensions(self): 44 '''return a tuple of dimensions Xndarray full_name''' 45 dimable = [] 46 for var in self.variables: 47 dimable += self.dims(var) 48 return tuple(sorted(set(nda for nda in dimable if nda in self.namedarrays))) 49 50 @property 51 def shape(self): 52 '''return an array with the length of dimensions''' 53 return [len(self[dim]) for dim in self.dimensions] 54 55 @property 56 def coordinates(self): 57 '''return a tuple of coordinates Xndarray full_name''' 58 dims = set(self.dimensions) 59 if not dims: 60 return () 61 return tuple(sorted(set(xnda.name for xnda in self.xnd 62 if xnda.xtype == 'variable' and set(xnda.links) != dims))) 63 64 @property 65 def data_vars(self): 66 '''return a tuple of data_vars Xndarray full_name''' 67 dims = set(self.dimensions) 68 if not dims: 69 return self.variables 70 return tuple(sorted(xnda.name for xnda in self.xnd 71 if xnda.xtype == 'variable' and set(xnda.links) == dims)) 72 73 @property 74 def namedarrays(self): 75 '''return a tuple of namedarray Xndarray full_name''' 76 return tuple(sorted(xnda.name for xnda in self.xnd if xnda.xtype == 'namedarray')) 77 78 @property 79 def variables(self): 80 '''return a tuple of variables Xndarray full_name''' 81 return tuple(sorted(xnda.name for xnda in self.xnd if xnda.xtype == 'variable')) 82 83 @property 84 def undef_vars(self): 85 '''return a tuple of variables Xndarray full_name with inconsistent shape''' 86 return tuple(sorted(var for var in self.variables if self[var].shape != 87 [len(self[dim]) for dim in self.dims(var)])) 88 89 @property 90 def undef_links(self): 91 '''return a tuple of variables Xndarray full_name with inconsistent links''' 92 return tuple(sorted(link for var in self.variables for link in self[var].links 93 if not link in self.names)) 94 95 @property 96 def masks(self): 97 '''return a tuple of additional Xndarray full_name with boolean ntv_type''' 98 return tuple(sorted(xnda.full_name for xnda in self.xnd 99 if xnda.xtype == 'additional' and xnda.ntv_type == 'boolean')) 100 101 @property 102 def data_add(self): 103 '''return a tuple of additional Xndarray full_name with not boolean ntv_type''' 104 return tuple(sorted(xnda.full_name for xnda in self.xnd 105 if xnda.xtype == 'additional' and xnda.ntv_type != 'boolean')) 106 107 @property 108 def metadata(self): 109 '''return a tuple of metadata Xndarray full_name''' 110 return tuple(sorted(xnda.full_name for xnda in self.xnd if xnda.xtype == 'meta')) 111 112 @property 113 def uniques(self): 114 '''return a tuple of unique Xndarray full_name''' 115 return tuple(full_name for full_name in self.namedarrays if len(self[full_name]) == 1) 116 117 @property 118 def additionals(self): 119 '''return a tuple of additionals Xndarray full_name''' 120 return tuple(sorted(xnda.full_name for xnda in self.xnd if xnda.xtype == 'additional')) 121 122 def group(self, grp): 123 '''return a tuple of Xndarray full_name with the same name''' 124 if isinstance(grp, str): 125 return tuple(sorted(xnda.full_name for xnda in self.xnd 126 if grp in (xnda.name, xnda.full_name))) 127 return tuple(sorted(nam for gr_nam in grp for nam in self.group(gr_nam))) 128 129 def add_group(self, add_name): 130 '''return a tuple of Xndarray full_name with the same add_name''' 131 return tuple(sorted(xnda.full_name for xnda in self.xnd if xnda.add_name == add_name))
category of Xndarray (dynamic tuple of full_name) - see Xdataset docstring
32 @abstractmethod 33 def dims(self, var, json_name=False): 34 '''method defined in Xdataset class'''
method defined in Xdataset class
36 @property 37 def data_arrays(self): 38 '''return a tuple of data_arrays Xndarray full_name''' 39 return tuple(sorted(nda for nda in self.namedarrays 40 if not nda in self.dimensions + self.uniques))
return a tuple of data_arrays Xndarray full_name
42 @property 43 def dimensions(self): 44 '''return a tuple of dimensions Xndarray full_name''' 45 dimable = [] 46 for var in self.variables: 47 dimable += self.dims(var) 48 return tuple(sorted(set(nda for nda in dimable if nda in self.namedarrays)))
return a tuple of dimensions Xndarray full_name
50 @property 51 def shape(self): 52 '''return an array with the length of dimensions''' 53 return [len(self[dim]) for dim in self.dimensions]
return an array with the length of dimensions
55 @property 56 def coordinates(self): 57 '''return a tuple of coordinates Xndarray full_name''' 58 dims = set(self.dimensions) 59 if not dims: 60 return () 61 return tuple(sorted(set(xnda.name for xnda in self.xnd 62 if xnda.xtype == 'variable' and set(xnda.links) != dims)))
return a tuple of coordinates Xndarray full_name
64 @property 65 def data_vars(self): 66 '''return a tuple of data_vars Xndarray full_name''' 67 dims = set(self.dimensions) 68 if not dims: 69 return self.variables 70 return tuple(sorted(xnda.name for xnda in self.xnd 71 if xnda.xtype == 'variable' and set(xnda.links) == dims))
return a tuple of data_vars Xndarray full_name
73 @property 74 def namedarrays(self): 75 '''return a tuple of namedarray Xndarray full_name''' 76 return tuple(sorted(xnda.name for xnda in self.xnd if xnda.xtype == 'namedarray'))
return a tuple of namedarray Xndarray full_name
78 @property 79 def variables(self): 80 '''return a tuple of variables Xndarray full_name''' 81 return tuple(sorted(xnda.name for xnda in self.xnd if xnda.xtype == 'variable'))
return a tuple of variables Xndarray full_name
83 @property 84 def undef_vars(self): 85 '''return a tuple of variables Xndarray full_name with inconsistent shape''' 86 return tuple(sorted(var for var in self.variables if self[var].shape != 87 [len(self[dim]) for dim in self.dims(var)]))
return a tuple of variables Xndarray full_name with inconsistent shape
89 @property 90 def undef_links(self): 91 '''return a tuple of variables Xndarray full_name with inconsistent links''' 92 return tuple(sorted(link for var in self.variables for link in self[var].links 93 if not link in self.names))
return a tuple of variables Xndarray full_name with inconsistent links
95 @property 96 def masks(self): 97 '''return a tuple of additional Xndarray full_name with boolean ntv_type''' 98 return tuple(sorted(xnda.full_name for xnda in self.xnd 99 if xnda.xtype == 'additional' and xnda.ntv_type == 'boolean'))
return a tuple of additional Xndarray full_name with boolean ntv_type
101 @property 102 def data_add(self): 103 '''return a tuple of additional Xndarray full_name with not boolean ntv_type''' 104 return tuple(sorted(xnda.full_name for xnda in self.xnd 105 if xnda.xtype == 'additional' and xnda.ntv_type != 'boolean'))
return a tuple of additional Xndarray full_name with not boolean ntv_type
107 @property 108 def metadata(self): 109 '''return a tuple of metadata Xndarray full_name''' 110 return tuple(sorted(xnda.full_name for xnda in self.xnd if xnda.xtype == 'meta'))
return a tuple of metadata Xndarray full_name
112 @property 113 def uniques(self): 114 '''return a tuple of unique Xndarray full_name''' 115 return tuple(full_name for full_name in self.namedarrays if len(self[full_name]) == 1)
return a tuple of unique Xndarray full_name
117 @property 118 def additionals(self): 119 '''return a tuple of additionals Xndarray full_name''' 120 return tuple(sorted(xnda.full_name for xnda in self.xnd if xnda.xtype == 'additional'))
return a tuple of additionals Xndarray full_name
122 def group(self, grp): 123 '''return a tuple of Xndarray full_name with the same name''' 124 if isinstance(grp, str): 125 return tuple(sorted(xnda.full_name for xnda in self.xnd 126 if grp in (xnda.name, xnda.full_name))) 127 return tuple(sorted(nam for gr_nam in grp for nam in self.group(gr_nam)))
return a tuple of Xndarray full_name with the same name
134class XdatasetInterface(ABC): 135 ''' Xdataset interface - see Xdataset docstring''' 136 137 name: str = NotImplemented 138 xnd: list = NotImplemented 139 140 @staticmethod 141 def read_json(jsn, **kwargs): 142 ''' convert json data into a Xdataset. 143 144 *Parameters* 145 146 - **convert** : boolean (default True) - If True, convert json data with 147 non Numpy ntv_type into Xndarray with python type 148 ''' 149 option = {'convert': True} | kwargs 150 jso = json.loads(jsn) if isinstance(jsn, str) else jsn 151 value, name = Ntv.decode_json(jso)[:2] 152 153 xnd = [Xndarray.read_json({key: val}, **option) 154 for key, val in value.items()] 155 return Xdataset(xnd, name) 156 157 def to_json(self, **kwargs): 158 ''' convert a Xdataset into json-value. 159 160 *Parameters* 161 162 - **encoded** : Boolean (default False) - json value if False else json text 163 - **header** : Boolean (default True) - including 'xdataset' type 164 - **notype** : list of Boolean (default list of None) - including data type if False 165 - **novalue** : Boolean (default False) - including value if False 166 - **noshape** : Boolean (default True) - if True, without shape if dim < 1 167 - **format** : list of string (default list of 'full') - representation 168 format of the ndarray, 169 ''' 170 notype = kwargs['notype'] if ('notype' in kwargs and isinstance(kwargs['notype'], list) and 171 len(kwargs['notype']) == len(self)) else [False] * len(self) 172 forma = kwargs['format'] if ('format' in kwargs and isinstance(kwargs['format'], list) and 173 len(kwargs['format']) == len(self)) else ['full'] * len(self) 174 noshape = kwargs.get('noshape', True) 175 dic_xnd = {} 176 for xna, notyp, forma in zip(self.xnd, notype, forma): 177 dic_xnd |= xna.to_json(notype=notyp, novalue=kwargs.get('novalue', False), 178 noshape=noshape, format=forma, header=False) 179 return Nutil.json_ntv(self.name, 'xdataset', dic_xnd, 180 header=kwargs.get('header', True), 181 encoded=kwargs.get('encoded', False)) 182 183 def to_xarray(self, **kwargs): 184 '''return a DataArray or a Dataset from a Xdataset 185 186 *Parameters* 187 188 - **dataset** : Boolean (default True) - if False and a single data_var, return a DataArray 189 ''' 190 return XarrayConnec.xexport(self, **kwargs) 191 192 @staticmethod 193 def from_xarray(xar, **kwargs): 194 '''return a Xdataset from a DataArray or a Dataset''' 195 return XarrayConnec.ximport(xar, Xdataset, **kwargs) 196 197 def to_scipp(self, **kwargs): 198 '''return a sc.DataArray or a sc.Dataset from a Xdataset 199 200 *Parameters* 201 202 - **dataset** : Boolean (default True) - if False and a single data_var, 203 return a DataArray 204 - **datagroup** : Boolean (default True) - if True return a DataGroup with 205 metadata and data_arrays 206 - **ntv_type** : Boolean (default True) - if True add ntv-type to the name 207 ''' 208 return ScippConnec.xexport(self, **kwargs) 209 210 @staticmethod 211 def from_scipp(sci, **kwargs): 212 '''return a Xdataset from a scipp object DataArray, Dataset or DataGroup''' 213 return ScippConnec.ximport(sci, Xdataset, **kwargs) 214 215 def to_nddata(self, **kwargs): 216 '''return a NDData from a Xdataset''' 217 return AstropyNDDataConnec.xexport(self, **kwargs) 218 219 @staticmethod 220 def from_nddata(ndd, **kwargs): 221 '''return a Xdataset from a NDData''' 222 return AstropyNDDataConnec.ximport(ndd, Xdataset, **kwargs) 223 224 def to_dataframe(self, **kwargs): 225 '''return a pd.DataFrame from a Xdataset''' 226 return PandasConnec.xexport(self, **kwargs) 227 228 @staticmethod 229 def from_dataframe(dfr, **kwargs): 230 '''return a Xdataset from a pd.DataFrame''' 231 return PandasConnec.ximport(dfr, Xdataset, **kwargs)
Xdataset interface - see Xdataset docstring
140 @staticmethod 141 def read_json(jsn, **kwargs): 142 ''' convert json data into a Xdataset. 143 144 *Parameters* 145 146 - **convert** : boolean (default True) - If True, convert json data with 147 non Numpy ntv_type into Xndarray with python type 148 ''' 149 option = {'convert': True} | kwargs 150 jso = json.loads(jsn) if isinstance(jsn, str) else jsn 151 value, name = Ntv.decode_json(jso)[:2] 152 153 xnd = [Xndarray.read_json({key: val}, **option) 154 for key, val in value.items()] 155 return Xdataset(xnd, name)
convert json data into a Xdataset.
Parameters
- convert : boolean (default True) - If True, convert json data with non Numpy ntv_type into Xndarray with python type
157 def to_json(self, **kwargs): 158 ''' convert a Xdataset into json-value. 159 160 *Parameters* 161 162 - **encoded** : Boolean (default False) - json value if False else json text 163 - **header** : Boolean (default True) - including 'xdataset' type 164 - **notype** : list of Boolean (default list of None) - including data type if False 165 - **novalue** : Boolean (default False) - including value if False 166 - **noshape** : Boolean (default True) - if True, without shape if dim < 1 167 - **format** : list of string (default list of 'full') - representation 168 format of the ndarray, 169 ''' 170 notype = kwargs['notype'] if ('notype' in kwargs and isinstance(kwargs['notype'], list) and 171 len(kwargs['notype']) == len(self)) else [False] * len(self) 172 forma = kwargs['format'] if ('format' in kwargs and isinstance(kwargs['format'], list) and 173 len(kwargs['format']) == len(self)) else ['full'] * len(self) 174 noshape = kwargs.get('noshape', True) 175 dic_xnd = {} 176 for xna, notyp, forma in zip(self.xnd, notype, forma): 177 dic_xnd |= xna.to_json(notype=notyp, novalue=kwargs.get('novalue', False), 178 noshape=noshape, format=forma, header=False) 179 return Nutil.json_ntv(self.name, 'xdataset', dic_xnd, 180 header=kwargs.get('header', True), 181 encoded=kwargs.get('encoded', False))
convert a Xdataset into json-value.
Parameters
- encoded : Boolean (default False) - json value if False else json text
- header : Boolean (default True) - including 'xdataset' type
- notype : list of Boolean (default list of None) - including data type if False
- novalue : Boolean (default False) - including value if False
- noshape : Boolean (default True) - if True, without shape if dim < 1
- format : list of string (default list of 'full') - representation format of the ndarray,
183 def to_xarray(self, **kwargs): 184 '''return a DataArray or a Dataset from a Xdataset 185 186 *Parameters* 187 188 - **dataset** : Boolean (default True) - if False and a single data_var, return a DataArray 189 ''' 190 return XarrayConnec.xexport(self, **kwargs)
return a DataArray or a Dataset from a Xdataset
Parameters
- dataset : Boolean (default True) - if False and a single data_var, return a DataArray
192 @staticmethod 193 def from_xarray(xar, **kwargs): 194 '''return a Xdataset from a DataArray or a Dataset''' 195 return XarrayConnec.ximport(xar, Xdataset, **kwargs)
return a Xdataset from a DataArray or a Dataset
197 def to_scipp(self, **kwargs): 198 '''return a sc.DataArray or a sc.Dataset from a Xdataset 199 200 *Parameters* 201 202 - **dataset** : Boolean (default True) - if False and a single data_var, 203 return a DataArray 204 - **datagroup** : Boolean (default True) - if True return a DataGroup with 205 metadata and data_arrays 206 - **ntv_type** : Boolean (default True) - if True add ntv-type to the name 207 ''' 208 return ScippConnec.xexport(self, **kwargs)
return a sc.DataArray or a sc.Dataset from a Xdataset
Parameters
- dataset : Boolean (default True) - if False and a single data_var, return a DataArray
- datagroup : Boolean (default True) - if True return a DataGroup with metadata and data_arrays
- ntv_type : Boolean (default True) - if True add ntv-type to the name
210 @staticmethod 211 def from_scipp(sci, **kwargs): 212 '''return a Xdataset from a scipp object DataArray, Dataset or DataGroup''' 213 return ScippConnec.ximport(sci, Xdataset, **kwargs)
return a Xdataset from a scipp object DataArray, Dataset or DataGroup
215 def to_nddata(self, **kwargs): 216 '''return a NDData from a Xdataset''' 217 return AstropyNDDataConnec.xexport(self, **kwargs)
return a NDData from a Xdataset
219 @staticmethod 220 def from_nddata(ndd, **kwargs): 221 '''return a Xdataset from a NDData''' 222 return AstropyNDDataConnec.ximport(ndd, Xdataset, **kwargs)
return a Xdataset from a NDData
234class Xdataset(XdatasetCategory, XdatasetInterface): 235 ''' Representation of a multidimensional Dataset 236 237 *Attributes :* 238 - **name** : String - name of the Xdataset 239 - **xnd**: list of Xndarray 240 241 *dynamic values (@property)* 242 - `xtype` 243 - `validity` 244 - `dic_xnd` 245 - `partition` 246 - `length` 247 - `info` 248 249 *methods* 250 - `parent` 251 - `dims` 252 - `shape_dims` 253 - `to_canonical` 254 - `to_ndarray` 255 - `to_darray` 256 257 *XdatasetCategory (@property)* 258 - `names` 259 - `data_arrays` 260 - `dimensions` 261 - `coordinates` 262 - `data_vars` 263 - `namedarrays` 264 - `variables` 265 - `undef_vars` 266 - `undef_links` 267 - `masks` 268 - `data_add` 269 - `meta` 270 - `metadata` 271 - `uniques` 272 - `additionals` 273 - `group` 274 - `add_group` 275 276 *XdatasetInterface methods * 277 - `read_json` (static) 278 - `to_json` 279 - `from_xarray` (static) 280 - `to_xarray` 281 - `from_scipp` (static) 282 - `to_scipp` 283 - `from_nddata` (static) 284 - `to_nddata` 285 - `from_dataframe` (static) 286 - `to_dataframe` 287 ''' 288 289 def __init__(self, xnd=None, name=None): 290 '''Xdataset constructor 291 292 *Parameters* 293 294 - **xnd** : Xdataset/Xndarray/list of Xndarray (default None), 295 - **name** : String (default None) - name of the Xdataset 296 ''' 297 self.name = name 298 match xnd: 299 case list(): 300 self.xnd = xnd 301 case xdat if isinstance(xdat, Xdataset): 302 self.name = xdat.name 303 self.xnd = xdat.xnd 304 case xnda if isinstance(xnda, Xndarray): 305 self.xnd = [xnda] 306 case _: 307 self.xnd = [] 308 309 def __repr__(self): 310 '''return classname and number of value''' 311 return (self.__class__.__name__ + '[' + str(len(self)) + ']\n' + 312 pprint.pformat(self.to_json(novalue=True, header=False, noshape=False))) 313 314 def __str__(self): 315 '''return json string format''' 316 return json.dumps(self.to_json()) 317 318 def __eq__(self, other): 319 '''equal if xnd are equal''' 320 for xnda in self.xnd: 321 if not xnda in other: 322 return False 323 for xnda in other.xnd: 324 if not xnda in self: 325 return False 326 return True 327 328 def __len__(self): 329 '''number of Xndarray''' 330 return len(self.xnd) 331 332 def __contains__(self, item): 333 ''' item of xnd''' 334 return item in self.xnd 335 336 def __getitem__(self, selec): 337 ''' return Xndarray or tuple of Xndarray with selec: 338 - string : name of a xndarray, 339 - integer : index of a xndarray, 340 - index selector : index interval 341 - tuple : names or index ''' 342 if selec is None or selec == '' or selec in ([], ()): 343 return self 344 if isinstance(selec, (list, tuple)) and len(selec) == 1: 345 selec = selec[0] 346 if isinstance(selec, tuple): 347 return [self[i] for i in selec] 348 if isinstance(selec, str): 349 return self.dic_xnd[selec] 350 if isinstance(selec, list): 351 return self[selec[0]][selec[1:]] 352 return self.xnd[selec] 353 354 def __delitem__(self, ind): 355 '''remove a Xndarray (ind is index, name or tuple of names).''' 356 if isinstance(ind, int): 357 del self.xnd[ind] 358 elif isinstance(ind, str): 359 del self.xnd[self.names.index(ind)] 360 elif isinstance(ind, tuple): 361 ind_n = [self.names[i] if isinstance(i, int) else i for i in ind] 362 for i in ind_n: 363 del self[i] 364 365 def __copy__(self): 366 ''' Copy all the data ''' 367 return self.__class__(self) 368 369 def parent(self, var): 370 '''return the Xndarray parent (where the full_name is equal to the name)''' 371 if var.name in self.names: 372 return self[var.name] 373 return var 374 375 def dims(self, var, json_name=False): 376 '''return the list of parent namedarrays of the links of a Xndarray 377 378 *parameters* 379 380 - **var**: string - full_name of the Xndarray 381 - **json_name**: boolean (defaut False) - if True return json_name else full_name 382 ''' 383 if not var in self.names: 384 return None 385 if self[var].add_name and not self[var].links: 386 return self.dims(self[var].name, json_name) 387 if var in self.namedarrays: 388 return [self[var].json_name if json_name else var] 389 if not var in self.variables + self.additionals: 390 return None 391 list_dims = [] 392 for link in self[var].links: 393 list_dims += self.dims(link, json_name) if self.dims(link, 394 json_name) else [link] 395 return list_dims 396 397 def shape_dims(self, var): 398 '''return a shape with the dimensions associated to the var full_name''' 399 return [len(self[dim]) for dim in self.dims(var) 400 ] if set(self.dims(var)) <= set(self.names) else None 401 402 @property 403 def validity(self): 404 '''return the validity state: 'inconsistent', 'undifined' or 'valid' ''' 405 for xnda in self: 406 if xnda.mode in ['relative', 'inconsistent']: 407 return 'undefined' 408 if self.undef_links or self.undef_vars: 409 return 'inconsistent' 410 return 'valid' 411 412 @property 413 def xtype(self): 414 '''return the Xdataset type: 'meta', 'group', 'mono', 'multi' ''' 415 if self.metadata and not (self.additionals or self.variables or 416 self.namedarrays): 417 return 'meta' 418 if self.validity != 'valid': 419 return 'group' 420 match len(self.data_vars): 421 case 0: 422 return 'group' 423 case 1: 424 return 'mono' 425 case _: 426 return 'multi' 427 428 @property 429 def dic_xnd(self): 430 '''return a dict of Xndarray where key is the full_name''' 431 return {xnda.full_name: xnda for xnda in self.xnd} 432 433 @property 434 def length(self): 435 '''return the max length of Xndarray''' 436 return max(len(xnda) for xnda in self.xnd) 437 438 @property 439 def names(self): 440 '''return a tuple with the Xndarray full_name''' 441 return tuple(xnda.full_name for xnda in self.xnd) 442 443 @property 444 def partition(self): 445 '''return a dict of Xndarray grouped with category''' 446 dic = {} 447 dic |= {'data_vars': list(self.data_vars)} if self.data_vars else {} 448 dic |= {'data_arrays': list(self.data_arrays) 449 } if self.data_arrays else {} 450 dic |= {'dimensions': list(self.dimensions)} if self.dimensions else {} 451 dic |= {'coordinates': list(self.coordinates) 452 } if self.coordinates else {} 453 dic |= {'additionals': list(self.additionals) 454 } if self.additionals else {} 455 dic |= {'metadata': list(self.metadata)} if self.metadata else {} 456 dic |= {'uniques': list(self.uniques)} if self.uniques else {} 457 return dic 458 459 @property 460 def info(self): 461 '''return a dict with Xdataset information ''' 462 inf = {'name': self.name, 'xtype': self.xtype} | self.partition 463 inf['validity'] = self.validity 464 inf['length'] = len(self[self.data_vars[0]]) if self.data_vars else 0 465 inf['width'] = len(self) 466 data = {name: {key: val for key, val in self[name].info.items() if key != 'name'} 467 for name in self.names} 468 return {'structure': {key: val for key, val in inf.items() if val}, 469 'data': {key: val for key, val in data.items() if val}} 470 471 @property 472 def tab_info(self): 473 '''return a dict with Xdataset information for tabular interface''' 474 info = self.info 475 data = info['data'] 476 t_info = {} 477 if 'dimensions' in info['structure']: 478 t_info['dimensions'] = info['structure']['dimensions'] 479 t_info['data'] = {name: {key: val for key, val in data[name].items() 480 if key in ['shape', 'xtype', 'meta', 'links']} 481 for name in data} 482 return t_info 483 484 def to_canonical(self): 485 '''remove optional links of the included Xndarray''' 486 for name in self.names: 487 if self[name].links in ([self[name].name], [name]): 488 self[name].links = None 489 for add in self.additionals: 490 if self[add].links in [self[self[add].name].links, 491 [self[add].name]]: 492 self[add].links = None 493 for unic in self.uniques: 494 self[unic].links = None 495 return self 496 497 def to_ndarray(self, full_name): 498 '''convert a Xndarray from a Xdataset in a np.ndarray''' 499 if self.shape_dims(full_name) is None: 500 data = self[full_name].ndarray 501 else: 502 data = self[full_name].darray.reshape(self.shape_dims(full_name)) 503 if data.dtype.name[:8] == 'datetime': 504 data = data.astype('datetime64[ns]') 505 return data 506 507 def to_darray(self, full_name): 508 '''convert a Xndarray from a Xdataset in a flattened np.ndarray''' 509 data = self[full_name].darray 510 if data.dtype.name[:8] == 'datetime': 511 data = data.astype('datetime64[ns]') 512 return data
Representation of a multidimensional Dataset
Attributes :
- name : String - name of the Xdataset
- xnd: list of Xndarray
dynamic values (@property)
methods
XdatasetCategory (@property)
names
data_arrays
dimensions
coordinates
data_vars
namedarrays
variables
undef_vars
undef_links
masks
data_add
meta
metadata
uniques
additionals
group
add_group
*XdatasetInterface methods *
read_json
(static)to_json
from_xarray
(static)to_xarray
from_scipp
(static)to_scipp
from_nddata
(static)to_nddata
from_dataframe
(static)to_dataframe
289 def __init__(self, xnd=None, name=None): 290 '''Xdataset constructor 291 292 *Parameters* 293 294 - **xnd** : Xdataset/Xndarray/list of Xndarray (default None), 295 - **name** : String (default None) - name of the Xdataset 296 ''' 297 self.name = name 298 match xnd: 299 case list(): 300 self.xnd = xnd 301 case xdat if isinstance(xdat, Xdataset): 302 self.name = xdat.name 303 self.xnd = xdat.xnd 304 case xnda if isinstance(xnda, Xndarray): 305 self.xnd = [xnda] 306 case _: 307 self.xnd = []
Xdataset constructor
Parameters
- xnd : Xdataset/Xndarray/list of Xndarray (default None),
- name : String (default None) - name of the Xdataset
369 def parent(self, var): 370 '''return the Xndarray parent (where the full_name is equal to the name)''' 371 if var.name in self.names: 372 return self[var.name] 373 return var
return the Xndarray parent (where the full_name is equal to the name)
375 def dims(self, var, json_name=False): 376 '''return the list of parent namedarrays of the links of a Xndarray 377 378 *parameters* 379 380 - **var**: string - full_name of the Xndarray 381 - **json_name**: boolean (defaut False) - if True return json_name else full_name 382 ''' 383 if not var in self.names: 384 return None 385 if self[var].add_name and not self[var].links: 386 return self.dims(self[var].name, json_name) 387 if var in self.namedarrays: 388 return [self[var].json_name if json_name else var] 389 if not var in self.variables + self.additionals: 390 return None 391 list_dims = [] 392 for link in self[var].links: 393 list_dims += self.dims(link, json_name) if self.dims(link, 394 json_name) else [link] 395 return list_dims
return the list of parent namedarrays of the links of a Xndarray
parameters
- var: string - full_name of the Xndarray
- json_name: boolean (defaut False) - if True return json_name else full_name
397 def shape_dims(self, var): 398 '''return a shape with the dimensions associated to the var full_name''' 399 return [len(self[dim]) for dim in self.dims(var) 400 ] if set(self.dims(var)) <= set(self.names) else None
return a shape with the dimensions associated to the var full_name
402 @property 403 def validity(self): 404 '''return the validity state: 'inconsistent', 'undifined' or 'valid' ''' 405 for xnda in self: 406 if xnda.mode in ['relative', 'inconsistent']: 407 return 'undefined' 408 if self.undef_links or self.undef_vars: 409 return 'inconsistent' 410 return 'valid'
return the validity state: 'inconsistent', 'undifined' or 'valid'
412 @property 413 def xtype(self): 414 '''return the Xdataset type: 'meta', 'group', 'mono', 'multi' ''' 415 if self.metadata and not (self.additionals or self.variables or 416 self.namedarrays): 417 return 'meta' 418 if self.validity != 'valid': 419 return 'group' 420 match len(self.data_vars): 421 case 0: 422 return 'group' 423 case 1: 424 return 'mono' 425 case _: 426 return 'multi'
return the Xdataset type: 'meta', 'group', 'mono', 'multi'
428 @property 429 def dic_xnd(self): 430 '''return a dict of Xndarray where key is the full_name''' 431 return {xnda.full_name: xnda for xnda in self.xnd}
return a dict of Xndarray where key is the full_name
433 @property 434 def length(self): 435 '''return the max length of Xndarray''' 436 return max(len(xnda) for xnda in self.xnd)
return the max length of Xndarray
438 @property 439 def names(self): 440 '''return a tuple with the Xndarray full_name''' 441 return tuple(xnda.full_name for xnda in self.xnd)
return a tuple with the Xndarray full_name
443 @property 444 def partition(self): 445 '''return a dict of Xndarray grouped with category''' 446 dic = {} 447 dic |= {'data_vars': list(self.data_vars)} if self.data_vars else {} 448 dic |= {'data_arrays': list(self.data_arrays) 449 } if self.data_arrays else {} 450 dic |= {'dimensions': list(self.dimensions)} if self.dimensions else {} 451 dic |= {'coordinates': list(self.coordinates) 452 } if self.coordinates else {} 453 dic |= {'additionals': list(self.additionals) 454 } if self.additionals else {} 455 dic |= {'metadata': list(self.metadata)} if self.metadata else {} 456 dic |= {'uniques': list(self.uniques)} if self.uniques else {} 457 return dic
return a dict of Xndarray grouped with category
459 @property 460 def info(self): 461 '''return a dict with Xdataset information ''' 462 inf = {'name': self.name, 'xtype': self.xtype} | self.partition 463 inf['validity'] = self.validity 464 inf['length'] = len(self[self.data_vars[0]]) if self.data_vars else 0 465 inf['width'] = len(self) 466 data = {name: {key: val for key, val in self[name].info.items() if key != 'name'} 467 for name in self.names} 468 return {'structure': {key: val for key, val in inf.items() if val}, 469 'data': {key: val for key, val in data.items() if val}}
return a dict with Xdataset information
471 @property 472 def tab_info(self): 473 '''return a dict with Xdataset information for tabular interface''' 474 info = self.info 475 data = info['data'] 476 t_info = {} 477 if 'dimensions' in info['structure']: 478 t_info['dimensions'] = info['structure']['dimensions'] 479 t_info['data'] = {name: {key: val for key, val in data[name].items() 480 if key in ['shape', 'xtype', 'meta', 'links']} 481 for name in data} 482 return t_info
return a dict with Xdataset information for tabular interface
484 def to_canonical(self): 485 '''remove optional links of the included Xndarray''' 486 for name in self.names: 487 if self[name].links in ([self[name].name], [name]): 488 self[name].links = None 489 for add in self.additionals: 490 if self[add].links in [self[self[add].name].links, 491 [self[add].name]]: 492 self[add].links = None 493 for unic in self.uniques: 494 self[unic].links = None 495 return self
remove optional links of the included Xndarray
497 def to_ndarray(self, full_name): 498 '''convert a Xndarray from a Xdataset in a np.ndarray''' 499 if self.shape_dims(full_name) is None: 500 data = self[full_name].ndarray 501 else: 502 data = self[full_name].darray.reshape(self.shape_dims(full_name)) 503 if data.dtype.name[:8] == 'datetime': 504 data = data.astype('datetime64[ns]') 505 return data
convert a Xndarray from a Xdataset in a np.ndarray
507 def to_darray(self, full_name): 508 '''convert a Xndarray from a Xdataset in a flattened np.ndarray''' 509 data = self[full_name].darray 510 if data.dtype.name[:8] == 'datetime': 511 data = data.astype('datetime64[ns]') 512 return data
convert a Xndarray from a Xdataset in a flattened np.ndarray