ntv-numpy.ntv_numpy.ndarray

@author: Philippe@loco-labs.io

The ndarray module is part of the ntv-numpy.ntv_numpy package (specification document).

It contains the classes Ndarray, Nutil, NdarrayError for the JSON interface of numpy.ndarrays.

For more information, see the user guide or the github repository.

  1# -*- coding: utf-8 -*-
  2"""
  3@author: Philippe@loco-labs.io
  4
  5The `ndarray` module is part of the `ntv-numpy.ntv_numpy` package
  6([specification document](
  7https://loco-philippe.github.io/ES/JSON%20semantic%20format%20(JSON-NTV).htm)).
  8
  9It contains the classes `Ndarray`, `Nutil`, `NdarrayError` for the JSON interface
 10of numpy.ndarrays.
 11
 12For more information, see the
 13[user guide](https://loco-philippe.github.io/ntv-numpy/docs/user_guide.html)
 14 or the [github repository](https://github.com/loco-philippe/ntv-numpy).
 15
 16"""
 17
 18import datetime
 19import json
 20
 21from decimal import Decimal
 22import numpy as np
 23from json_ntv import Ntv, ShapelyConnec, Datatype, NtvConnector
 24from ntv_numpy.data_array import Dfull, Dcomplete, Darray, Dutil
 25
 26
 27class Ndarray:
 28    ''' The Ndarray class is the JSON interface of numpy.ndarrays.
 29
 30    *static methods*
 31    - `read_json`
 32    - `to_json`
 33    - `equals`
 34    '''
 35
 36    def __init__(self, dar, ntv_type=None, shape=None):
 37        '''Ndarray constructor.
 38
 39        *Parameters*
 40
 41        - **dar**: Darray or np.ndarray - data to represent
 42        - **shape** : list of integer (default None) - length of dimensions
 43        - **ntv_type**: string (default None) - NTVtype to apply
 44        '''
 45        dar = [None] if isinstance(dar, list) and len(dar) == 0 else dar
 46        if isinstance(dar, Ndarray):
 47            self.uri = dar.uri
 48            self.is_json = dar.is_json
 49            self.ntvtype = dar.ntvtype
 50            self.shape = dar.shape
 51            self.darray = dar.darray
 52            return
 53        if isinstance(dar, str):
 54            self.uri = dar
 55            self.is_json = True
 56            self.ntvtype = Datatype(ntv_type) if ntv_type else None
 57            self.shape = shape
 58            self.darray = None
 59            return
 60        if shape:
 61            dar = Dfull(dar, dtype=Nutil.dtype(ntv_type), unidim=True).data
 62        else:
 63            # dar = np.array(dar if isinstance(dar, (list, np.ndarray)) else [dar],
 64            dar = np.array(dar, dtype=Nutil.dtype(ntv_type))
 65            shape = list(dar.shape)
 66        dar = np.array(dar).reshape(-1)
 67        # ntv_type = Nutil.nda_ntv_type(dar) if not (ntv_type or dar is None) else ntv_type
 68        ntv_type = Nutil.nda_ntv_type(dar, ntv_type)
 69        self.uri = None
 70        self.is_json = Nutil.is_json(dar[0])
 71        self.ntvtype = Datatype(ntv_type)
 72        self.shape = shape
 73        self.darray = dar.astype(Nutil.dtype(str(self.ntvtype)))
 74
 75    def __repr__(self):
 76        '''return classname, the shape and the ntv_type'''
 77        uri = self.uri if self.uri else ''
 78        typ = self.ntv_type if self.ntv_type else ''
 79        sha = str(self.shape) if self.shape else ''
 80        u_t = ', ' if uri and typ + sha else ''
 81        t_s = ', ' if typ and sha else ''
 82        return self.__class__.__name__ + '(' + uri + u_t + typ + t_s + sha + ')'
 83
 84    def __str__(self):
 85        '''return json string format'''
 86        return json.dumps(self.to_json())
 87
 88    def __eq__(self, other):
 89        ''' equal if attributes are equal'''
 90        if self.ntv_type != other.ntv_type:
 91            return False
 92        if self.uri != other.uri:
 93            return False
 94        if self.shape != other.shape:
 95            return False
 96        if self.darray is None and other.darray is None:
 97            return True
 98        if self.darray is None or other.darray is None:
 99            return False
100        return Dutil.equals(self.darray, other.darray)
101
102    def __len__(self):
103        ''' len of ndarray'''
104        # return len(self.darray) if self.darray is not None else Ndarray.len_shape(self.shape)
105        return len(self.darray) if self.darray is not None else 0
106
107    def __contains__(self, item):
108        ''' item of darray values'''
109        return item in self.darray if self.darray is not None else None
110
111    def __getitem__(self, ind):
112        ''' return darray value item'''
113        if self.darray is None:
114            return None
115        if isinstance(ind, tuple):
116            return [self.darray[i] for i in ind]
117        return self.darray[ind]
118
119    def __copy__(self):
120        ''' Copy all the data '''
121        return self.__class__(self)
122
123    def __array__(self):
124        '''numpy array interface'''
125        return self.ndarray
126
127    @property
128    def ntv_type(self):
129        ''' string representation of ntvtype'''
130        return str(self.ntvtype) if self.ntvtype else None
131
132    @property
133    def ndarray(self):
134        '''representation with a np.ndarray not flattened'''
135        return self.darray.reshape(self.shape) if not self.darray is None else None
136
137    def update(self, nda, nda_uri=True):
138        '''update uri and darray and return the result (True, False)
139
140        *Parameters*
141
142        - **nda** : string, list, np.ndarray, Ndarray - data to include
143        - **nda_uri** : boolean (default True) - if True, existing shape and
144        ntv_type are not updated (but are created if not existing)'''
145        if not nda_uri and not (self.shape is None or nda.shape is None
146                                ) and self.shape != nda.shape:
147            return False
148        if not nda_uri and not (self.ntv_type is None or nda.ntv_type is None
149                                ) and self.ntv_type != nda.ntv_type:
150            return False
151        if nda_uri:
152            len_s = self.len_shape(self.shape)
153            if len_s and len(nda) and len_s != len(nda):
154                return False
155            self.ntvtype = nda.ntvtype if self.ntv_type is None else self.ntvtype
156            self.shape = nda.shape if self.shape is None else self.shape
157        else:
158            self.ntvtype = nda.ntvtype if not nda.ntv_type is None else self.ntvtype
159            self.shape = nda.shape if not nda.shape is None else self.shape
160        self.uri, self.darray = (
161            nda.uri, None) if nda.uri else (None, nda.darray)
162        return True
163
164    def set_array(self, darray):
165        '''set a new darray and remove uri, return the result (True, False)
166
167        *Parameters*
168
169        - **darray** : list, np.ndarray, Ndarray - data to include'''
170        ndarray = Ndarray(darray)
171        darray = ndarray.darray
172        ntv_type = ndarray.ntv_type
173        shape = ndarray.shape
174        new_shape = shape if self.shape is None else self.shape
175        new_ntv_type = ntv_type if self.ntv_type is None else self.ntv_type
176        if (len(darray) != Ndarray.len_shape(new_shape) or
177                new_ntv_type != ntv_type or new_shape != shape):
178            return False
179        self.uri = None
180        self.darray = darray
181        self.ntvtype = Datatype(new_ntv_type)
182        self.shape = new_shape
183        return True
184
185    def set_uri(self, uri, no_ntv_type=False, no_shape=False):
186        '''set a new uri and remove ndarray and optionaly ntv_type and shape.
187        Return the result (True, False)
188
189        *Parameters*
190
191        - **uri** : string - URI of the Ndarray
192        - **no_ntv_type** : boolean (default False) - If True, ntv_type is None
193        - **no_shape** : boolean (default False) - If True, shape is None
194        '''
195        if not isinstance(uri, str) or not uri:
196            return False
197        self.uri = uri
198        self.darray = None
199        self.ntvtype = None if no_ntv_type else self.ntvtype
200        self.shape = None if no_shape else self.shape
201        return True
202
203    def to_ndarray(self):
204        '''representation with a np.ndarray not flattened'''
205        return self.ndarray
206
207    @property
208    def mode(self):
209        '''representation mode of the darray/uri data (relative, absolute,
210        undefined, inconsistent)'''
211        match [self.darray, self.uri]:
212            case [None, str()]:
213                return 'relative'
214            case [None, None]:
215                return 'undefined'
216            case [_, None]:
217                return 'absolute'
218            case _:
219                return 'inconsistent'
220
221    @staticmethod
222    def read_json(jsn, **kwargs):
223        ''' convert json ntv_value into a ndarray.
224
225        *Parameters*
226
227        - **convert** : boolean (default True) - If True, convert json data with
228        non Numpy ntv_type into data with python type
229        '''
230        option = {'convert': True} | kwargs
231        jso = json.loads(jsn) if isinstance(jsn, str) else jsn
232        ntv_value, = Ntv.decode_json(jso)[:1]
233
234        ntv_type = None
235        shape = None
236        match ntv_value[:-1]:
237            case []: ...
238            case [ntv_type, shape]: ...
239            case [str(ntv_type)]: ...
240            case [list(shape)]: ...
241        unidim = not shape is None
242        if isinstance(ntv_value[-1], str):
243            return Ndarray(ntv_value[-1], shape=shape, ntv_type=ntv_type)
244        darray = Darray.read_json(ntv_value[-1], dtype=Nutil.dtype(ntv_type),
245                                  unidim=unidim)
246        darray.data = Nutil.convert(ntv_type, darray.data, tojson=False,
247                                    convert=option['convert'])
248        return Ndarray(darray.values, shape=shape, ntv_type=ntv_type)
249
250    def to_json(self, **kwargs):
251        ''' convert a Ndarray into json-value
252
253        *Parameters*
254
255        - **noshape** : Boolean (default True) - if True, without shape if dim < 1
256        - **notype** : Boolean (default False) - including data type if False
257        - **novalue** : Boolean (default False) - including value if False
258        - **format** : string (default 'full') - representation format of the ndarray,
259        - **encoded** : Boolean (default False) - json-value if False else json-text
260        - **header** : Boolean (default True) - including ndarray type
261        '''
262        option = {'format': 'full', 'header': True, 'encoded': False,
263                  'notype': False, 'noshape': True, 'novalue': False} | kwargs
264        if self.mode in ['undefined', 'inconsistent']:
265            return None
266        if self.mode == 'absolute' and len(self.darray) == 0:
267            return [[]]
268
269        shape = None if not self.shape or (len(self.shape) < 2 and
270                                           option['noshape']) else self.shape
271
272        if self.mode == 'relative':
273            js_val = self.uri
274        else:
275            js_val = Nutil.ntv_val(self.ntv_type, self.darray, option['format'],
276                                   self.is_json) if not option['novalue'] else ['-']
277
278        lis = [self.ntv_type if not option['notype'] else None, shape, js_val]
279        return Nutil.json_ntv(None, 'ndarray',
280                              [val for val in lis if not val is None],
281                              header=option['header'], encoded=option['encoded'])
282
283    @property
284    def info(self):
285        ''' infos of the Ndarray'''
286        inf = {'shape': self.shape}
287        inf['length'] = len(self)
288        inf['ntvtype'] = self.ntv_type
289        inf['shape'] = self.shape
290        inf['uri'] = self.uri
291        return {key: val for key, val in inf.items() if val}
292
293    @staticmethod
294    def len_shape(shape):
295        '''return a length from a shape (product of dimensions)'''
296        if not shape:
297            return 0
298        prod = 1
299        for dim in shape:
300            prod *= dim
301        return prod
302
303
304class Nutil:
305    '''ntv-ndarray utilities.
306
307    *static methods*
308    - `convert`
309    - `is_json`
310    - `ntv_val`
311    - `add_ext`
312    - `split_type`
313    - `ntv_type`
314    - `nda_ntv_type`
315    - `dtype`
316    - `json_ntv`
317    - `split_name`
318    - `split_json_name`
319
320    '''
321
322    DATATION_DT = {'date': 'datetime64[D]', 'year': 'datetime64[Y]',
323                   'yearmonth': 'datetime64[M]',
324                   'datetime': 'datetime64[s]', 'datetime[ms]': 'datetime64[ms]',
325                   'datetime[us]': 'datetime64[us]', 'datetime[ns]': 'datetime64[ns]',
326                   'datetime[ps]': 'datetime64[ps]', 'datetime[fs]': 'datetime64[fs]',
327                   'timedelta': 'timedelta64[s]', 'timedelta[ms]': 'timedelta64[ms]',
328                   'timedelta[us]': 'timedelta64[us]', 'timedelta[ns]': 'timedelta64[ns]',
329                   'timedelta[ps]': 'timedelta64[ps]', 'timedelta[fs]': 'timedelta64[fs]',
330                   'timedelta[D]': 'timedelta64[D]', 'timedelta[Y]': 'timedelta64[Y]',
331                   'timedelta[M]': 'timedelta64[M]'}
332    DT_DATATION = {val: key for key, val in DATATION_DT.items()}
333
334    # CONNECTOR_DT = {'field': 'Series', 'tab': 'DataFrame'}
335    CONNECTOR_DT = {'field': 'Series', 'tab': 'DataFrame'}
336    DT_CONNECTOR = {val: key for key, val in CONNECTOR_DT.items()}
337
338    PYTHON_DT = {'array': 'list', 'time': 'datetime.time',
339                 'object': 'dict', 'null': 'NoneType', 'decimal64': 'Decimal',
340                 'ndarray': 'ndarray', 'narray': 'narray'}
341    DT_PYTHON = {val: key for key, val in PYTHON_DT.items()}
342
343    # OTHER_DT = {'boolean': 'bool', 'string': 'str'}
344    OTHER_DT = {'boolean': 'bool', 'string': 'str', 'base16': 'bytes'}
345    DT_OTHER = {val: key for key, val in OTHER_DT.items()}
346
347    LOCATION_DT = {'point': 'Point',
348                   'line': 'LineString', 'polygon': 'Polygon'}
349    DT_LOCATION = {val: key for key, val in LOCATION_DT.items()}
350
351    NUMBER_DT = {'json': 'object', 'number': None, 'month': 'int', 'day': 'int',
352                 'wday': 'int', 'yday': 'int', 'week': 'hour', 'minute': 'int',
353                 'second': 'int'}
354    # STRING_DT = {'base16': 'str', 'base32': 'str', 'base64': 'str',
355    STRING_DT = {'base32': 'str', 'base64': 'str',
356                 'period': 'str', 'duration': 'str', 'jpointer': 'str',
357                 'uri': 'str', 'uriref': 'str', 'iri': 'str', 'iriref': 'str',
358                 'email': 'str', 'regex': 'str', 'hostname': 'str', 'ipv4': 'str',
359                 'ipv6': 'str', 'file': 'str', 'geojson': 'str', }
360    FORMAT_CLS = {'full': Dfull, 'complete': Dcomplete}
361    CONVERT_DT = {'object': 'object', 'array': 'object', 'json': 'object',
362                  'number': 'float', 'boolean': 'bool', 'null': 'object',
363                  'string': 'str', 'integer': 'int'}
364    STRUCT_DT = {'Ntv': 'object', 'NtvSingle': 'object', 'NtvList': 'object'}
365
366    DT_NTVTYPE = DT_DATATION | DT_LOCATION | DT_OTHER | DT_CONNECTOR | DT_PYTHON
367
368    @staticmethod
369    def is_json(obj):
370        ''' check if obj is a json structure and return True if obj is a json-value
371
372        *Parameters*
373
374        - **obj** : object to check'''
375        if obj is None:
376            return True
377        is_js = NtvConnector.is_json
378        match obj:
379            case str() | int() | float() | bool():
380                return True
381            case list() | tuple() as obj:
382                if not obj:
383                    return True
384                return min(is_js(obj_in) for obj_in in obj)
385            case dict() as obj:
386                if not obj:
387                    return True
388                if not min(isinstance(key, str) for key in obj.keys()):
389                    return False
390                return min(is_js(obj_in) for obj_in in obj.values())
391            case _:
392                return False
393
394    @staticmethod
395    def convert(ntv_type, nda, tojson=True, convert=True):
396        ''' convert np.ndarray with external NTVtype.
397
398        *Parameters*
399
400        - **ntv_type** : string - NTVtype deduced from the np.ndarray name_type and dtype,
401        - **nda** : np.ndarray to be converted.
402        - **tojson** : boolean (default True) - apply to json function
403        - **convert** : boolean (default True) - If True, convert json data with
404        non Numpy ntv_type into data with python type
405        '''
406        if tojson:
407            match ntv_type:
408                case dat if dat in Nutil.DATATION_DT:
409                    return nda.astype(Nutil.DATATION_DT[dat]).astype(str)
410                case 'bytes':
411                    return nda.astype('bytes').astype(str)
412                case 'time':
413                    return nda.astype(str)
414                case 'decimal64':
415                    return nda.astype(float)
416                case 'geojson':
417                    return np.frompyfunc(ShapelyConnec.to_geojson, 1, 1)(nda)
418                case _:
419                    return nda
420        else:
421            match [ntv_type, convert]:
422                case [None, _]:
423                    return nda
424                case [dat, _] if dat in Nutil.DATATION_DT:
425                    return nda.astype(Nutil.DATATION_DT[dat])
426                case [std, _] if std in Nutil.OTHER_DT:
427                    return nda.astype(Nutil.OTHER_DT[std])
428                case ['time', True]:
429                    return np.frompyfunc(datetime.time.fromisoformat, 1, 1)(nda)
430                case ['decimal64', True]:
431                    return np.frompyfunc(Decimal, 1, 1)(nda)
432                case ['narray', True]:
433                    nar = np.frompyfunc(Ndarray.read_json, 1, 1)(nda)
434                    return np.frompyfunc(Ndarray.to_ndarray, 1, 1)(nar)
435                case ['ndarray', True]:
436                    return np.frompyfunc(Ndarray.read_json, 1, 1)(nda)
437                case [python, _] if python in Nutil.PYTHON_DT:
438                    return nda.astype('object')
439                case [connec, True] if connec in Nutil.CONNECTOR_DT:
440                    return np.fromiter([NtvConnector.uncast(nd, None, connec)[0]
441                                        for nd in nda], dtype='object')
442                case [('point' | 'line' | 'polygon' | 'geometry'), True]:
443                    return np.frompyfunc(ShapelyConnec.to_geometry, 1, 1)(nda)
444                case [_, False]:
445                    return nda.astype(Nutil.CONVERT_DT[
446                        Nutil.dtype(ntv_type, convert=False)])
447                case _:
448                    return nda.astype(Nutil.dtype(ntv_type))
449
450        # float.fromhex(x.hex()) == x, bytes(bytearray.fromhex(x.hex())) == x
451    @staticmethod
452    def ntv_val(ntv_type, nda, form, is_json=False):
453        ''' convert a np.ndarray into NTV json-value.
454
455        *Parameters*
456
457        - **ntv_type** : string - NTVtype deduced from the ndarray, name_type and dtype,
458        - **nda** : ndarray to be converted.
459        - **form** : format of data ('full', 'complete', 'sparse', 'primary').
460        - **is_json** : boolean (defaut False) - True if nda data is Json data
461        '''
462        if form == 'complete' and len(nda) < 2:
463            raise NdarrayError(
464                "complete format is not available with ndarray length < 2")
465        Format = Nutil.FORMAT_CLS[form]
466        darray = Format(nda)
467        ref = darray.ref
468        coding = darray.coding
469        if is_json:
470            return Format(darray.data, ref=ref, coding=coding).to_json()
471        match ntv_type:
472            case 'narray':
473                data = [Ndarray(nd).to_json(header=False)
474                        for nd in darray.data]
475            case 'ndarray':
476                # data = [Ndarray.to_json(nd) for nd in darray.data]
477                data = [Ndarray(nd).to_json(header=False)
478                        for nd in darray.data]
479            case connec if connec in Nutil.CONNECTOR_DT:
480                data = [NtvConnector.cast(nd, None, connec)[0]
481                        for nd in darray.data]
482            case 'point' | 'line' | 'polygon' | 'geometry':
483                data = np.frompyfunc(ShapelyConnec.to_coord, 1, 1)(darray.data)
484            case None:
485                data = nda
486            case _:
487                data = Nutil.convert(ntv_type, darray.data)
488        return Format(data, ref=ref, coding=coding).to_json()
489
490    @staticmethod
491    def add_ext(typ, ext):
492        '''return extended type : "typ[ext]"'''
493        ext = '[' + ext + ']' if ext else ''
494        return '' if not typ else typ + ext
495
496    @staticmethod
497    def split_type(typ):
498        '''return a tuple with typ and extension'''
499        if not isinstance(typ, str):
500            return (None, None)
501        spl = typ.split('[', maxsplit=1)
502        return (spl[0], None) if len(spl) == 1 else (spl[0], spl[1][:-1])
503
504    @staticmethod
505    def split_json_name(string, notnone=False):
506        '''return a tuple with name, ntv_type from string'''
507        null = '' if notnone else None
508        if not string or string == ':':
509            return (null, null)
510        spl = string.rsplit(':', maxsplit=1)
511        if len(spl) == 1:
512            return (string, null)
513        if spl[0] == '':
514            return (null, spl[1])
515        sp0 = spl[0][:-1] if spl[0][-1] == ':' else spl[0]
516        return (null if sp0 == '' else sp0, null if spl[1] == '' else spl[1])
517
518    @staticmethod
519    def split_name(string):
520        '''return a list with name, add_name from string'''
521        if not string or string == '.':
522            return ['', '']
523        spl = string.split('.', maxsplit=1)
524        spl = [spl[0], ''] if len(spl) < 2 else spl
525        return spl
526
527    @staticmethod
528    def ntv_type(dtype, ntv_type=None, ext=None):
529        ''' return NTVtype from dtype, additional type and extension.
530
531        *Parameters*
532
533        - **dtype** : string - dtype of the ndarray
534        - **ntv_type** : string - additional type
535        - **ext** : string - type extension
536        '''
537        if ntv_type:
538            return Nutil.add_ext(ntv_type, ext)
539        match dtype:
540            case dat if dat in Nutil.DT_NTVTYPE:
541                return Nutil.add_ext(Nutil.DT_NTVTYPE[dat], ext)
542            case string if string[:3] == 'str':
543                return Nutil.add_ext('string', ext)
544            case byte if byte[:5] == 'bytes':
545                # return Nutil.add_ext('bytes', ext)
546                return Nutil.add_ext('base16', ext)
547            case _:
548                return Nutil.add_ext(dtype, ext)
549
550    @staticmethod
551    def nda_ntv_type(nda, ntv_type=None, ext=None):
552        '''return ntv_type from an ndarray, additional type and extension.
553
554        *Parameters*
555
556        - **nda** : ndarray - data used to calculate the ntv_type
557        - **ntv_type** : string - additional type
558        - **ext** : string - type extension
559        '''
560        if ntv_type or nda is None:
561            return ntv_type
562        dtype = nda.dtype.name
563        pytype = nda.flat[0].__class__.__name__
564        dtype = pytype if dtype == 'object' and not pytype in Nutil.STRUCT_DT else dtype
565        # dtype = pytype if dtype == 'object' and pytype in Nutil.DT_NTVTYPE else dtype
566        # dtype = nda.flat[0].__class__.__name__ if dtype == 'object' else dtype
567        return Nutil.ntv_type(dtype, ntv_type, ext)
568
569    @staticmethod
570    def dtype(ntv_type, convert=True):
571        ''' return dtype from ntv_type
572
573        *parameters*
574
575        - **convert** : boolean (default True) - if True, dtype if from converted data
576        '''
577        DTYPE = (Nutil.DATATION_DT | Nutil.NUMBER_DT | Nutil.OTHER_DT |
578                 Nutil.STRING_DT)
579        OBJECT = Nutil.LOCATION_DT | Nutil.CONNECTOR_DT | Nutil.PYTHON_DT
580        type_base = Nutil.split_type(ntv_type)[0]
581        if convert:
582            if type_base in OBJECT:
583                return 'object'
584            return DTYPE.get(ntv_type, DTYPE.get(type_base, type_base))
585        return Datatype(ntv_type).json_type
586
587    @staticmethod
588    def json_ntv(ntv_name, ntv_type, ntv_value, **kwargs):
589        ''' return the JSON representation of a NTV entity
590
591        *parameters*
592
593        - **ntv_name** : string - name of the NTV
594        - **ntv_type** : string - type of the NTV
595        - **ntv_value** : string - Json value of the NTV
596        - **encoded** : boolean (default False) - if True return JsonText else JsonValue
597        - **header** : boolean (default True) - if True include ntv_name + ntv_type
598        '''
599        name = ntv_name if ntv_name else ''
600        option = {'encoded': False, 'header': True} | kwargs
601        if option['header'] or name:
602            typ = ':' + ntv_type if option['header'] and ntv_type else ''
603            jsn = {name + typ: ntv_value} if name + typ else ntv_value
604        else:
605            jsn = ntv_value
606        if option['encoded']:
607            return json.dumps(jsn)
608        return jsn
609
610
611class NdarrayError(Exception):
612    '''Multidimensional exception'''
class Ndarray:
 28class Ndarray:
 29    ''' The Ndarray class is the JSON interface of numpy.ndarrays.
 30
 31    *static methods*
 32    - `read_json`
 33    - `to_json`
 34    - `equals`
 35    '''
 36
 37    def __init__(self, dar, ntv_type=None, shape=None):
 38        '''Ndarray constructor.
 39
 40        *Parameters*
 41
 42        - **dar**: Darray or np.ndarray - data to represent
 43        - **shape** : list of integer (default None) - length of dimensions
 44        - **ntv_type**: string (default None) - NTVtype to apply
 45        '''
 46        dar = [None] if isinstance(dar, list) and len(dar) == 0 else dar
 47        if isinstance(dar, Ndarray):
 48            self.uri = dar.uri
 49            self.is_json = dar.is_json
 50            self.ntvtype = dar.ntvtype
 51            self.shape = dar.shape
 52            self.darray = dar.darray
 53            return
 54        if isinstance(dar, str):
 55            self.uri = dar
 56            self.is_json = True
 57            self.ntvtype = Datatype(ntv_type) if ntv_type else None
 58            self.shape = shape
 59            self.darray = None
 60            return
 61        if shape:
 62            dar = Dfull(dar, dtype=Nutil.dtype(ntv_type), unidim=True).data
 63        else:
 64            # dar = np.array(dar if isinstance(dar, (list, np.ndarray)) else [dar],
 65            dar = np.array(dar, dtype=Nutil.dtype(ntv_type))
 66            shape = list(dar.shape)
 67        dar = np.array(dar).reshape(-1)
 68        # ntv_type = Nutil.nda_ntv_type(dar) if not (ntv_type or dar is None) else ntv_type
 69        ntv_type = Nutil.nda_ntv_type(dar, ntv_type)
 70        self.uri = None
 71        self.is_json = Nutil.is_json(dar[0])
 72        self.ntvtype = Datatype(ntv_type)
 73        self.shape = shape
 74        self.darray = dar.astype(Nutil.dtype(str(self.ntvtype)))
 75
 76    def __repr__(self):
 77        '''return classname, the shape and the ntv_type'''
 78        uri = self.uri if self.uri else ''
 79        typ = self.ntv_type if self.ntv_type else ''
 80        sha = str(self.shape) if self.shape else ''
 81        u_t = ', ' if uri and typ + sha else ''
 82        t_s = ', ' if typ and sha else ''
 83        return self.__class__.__name__ + '(' + uri + u_t + typ + t_s + sha + ')'
 84
 85    def __str__(self):
 86        '''return json string format'''
 87        return json.dumps(self.to_json())
 88
 89    def __eq__(self, other):
 90        ''' equal if attributes are equal'''
 91        if self.ntv_type != other.ntv_type:
 92            return False
 93        if self.uri != other.uri:
 94            return False
 95        if self.shape != other.shape:
 96            return False
 97        if self.darray is None and other.darray is None:
 98            return True
 99        if self.darray is None or other.darray is None:
100            return False
101        return Dutil.equals(self.darray, other.darray)
102
103    def __len__(self):
104        ''' len of ndarray'''
105        # return len(self.darray) if self.darray is not None else Ndarray.len_shape(self.shape)
106        return len(self.darray) if self.darray is not None else 0
107
108    def __contains__(self, item):
109        ''' item of darray values'''
110        return item in self.darray if self.darray is not None else None
111
112    def __getitem__(self, ind):
113        ''' return darray value item'''
114        if self.darray is None:
115            return None
116        if isinstance(ind, tuple):
117            return [self.darray[i] for i in ind]
118        return self.darray[ind]
119
120    def __copy__(self):
121        ''' Copy all the data '''
122        return self.__class__(self)
123
124    def __array__(self):
125        '''numpy array interface'''
126        return self.ndarray
127
128    @property
129    def ntv_type(self):
130        ''' string representation of ntvtype'''
131        return str(self.ntvtype) if self.ntvtype else None
132
133    @property
134    def ndarray(self):
135        '''representation with a np.ndarray not flattened'''
136        return self.darray.reshape(self.shape) if not self.darray is None else None
137
138    def update(self, nda, nda_uri=True):
139        '''update uri and darray and return the result (True, False)
140
141        *Parameters*
142
143        - **nda** : string, list, np.ndarray, Ndarray - data to include
144        - **nda_uri** : boolean (default True) - if True, existing shape and
145        ntv_type are not updated (but are created if not existing)'''
146        if not nda_uri and not (self.shape is None or nda.shape is None
147                                ) and self.shape != nda.shape:
148            return False
149        if not nda_uri and not (self.ntv_type is None or nda.ntv_type is None
150                                ) and self.ntv_type != nda.ntv_type:
151            return False
152        if nda_uri:
153            len_s = self.len_shape(self.shape)
154            if len_s and len(nda) and len_s != len(nda):
155                return False
156            self.ntvtype = nda.ntvtype if self.ntv_type is None else self.ntvtype
157            self.shape = nda.shape if self.shape is None else self.shape
158        else:
159            self.ntvtype = nda.ntvtype if not nda.ntv_type is None else self.ntvtype
160            self.shape = nda.shape if not nda.shape is None else self.shape
161        self.uri, self.darray = (
162            nda.uri, None) if nda.uri else (None, nda.darray)
163        return True
164
165    def set_array(self, darray):
166        '''set a new darray and remove uri, return the result (True, False)
167
168        *Parameters*
169
170        - **darray** : list, np.ndarray, Ndarray - data to include'''
171        ndarray = Ndarray(darray)
172        darray = ndarray.darray
173        ntv_type = ndarray.ntv_type
174        shape = ndarray.shape
175        new_shape = shape if self.shape is None else self.shape
176        new_ntv_type = ntv_type if self.ntv_type is None else self.ntv_type
177        if (len(darray) != Ndarray.len_shape(new_shape) or
178                new_ntv_type != ntv_type or new_shape != shape):
179            return False
180        self.uri = None
181        self.darray = darray
182        self.ntvtype = Datatype(new_ntv_type)
183        self.shape = new_shape
184        return True
185
186    def set_uri(self, uri, no_ntv_type=False, no_shape=False):
187        '''set a new uri and remove ndarray and optionaly ntv_type and shape.
188        Return the result (True, False)
189
190        *Parameters*
191
192        - **uri** : string - URI of the Ndarray
193        - **no_ntv_type** : boolean (default False) - If True, ntv_type is None
194        - **no_shape** : boolean (default False) - If True, shape is None
195        '''
196        if not isinstance(uri, str) or not uri:
197            return False
198        self.uri = uri
199        self.darray = None
200        self.ntvtype = None if no_ntv_type else self.ntvtype
201        self.shape = None if no_shape else self.shape
202        return True
203
204    def to_ndarray(self):
205        '''representation with a np.ndarray not flattened'''
206        return self.ndarray
207
208    @property
209    def mode(self):
210        '''representation mode of the darray/uri data (relative, absolute,
211        undefined, inconsistent)'''
212        match [self.darray, self.uri]:
213            case [None, str()]:
214                return 'relative'
215            case [None, None]:
216                return 'undefined'
217            case [_, None]:
218                return 'absolute'
219            case _:
220                return 'inconsistent'
221
222    @staticmethod
223    def read_json(jsn, **kwargs):
224        ''' convert json ntv_value into a ndarray.
225
226        *Parameters*
227
228        - **convert** : boolean (default True) - If True, convert json data with
229        non Numpy ntv_type into data with python type
230        '''
231        option = {'convert': True} | kwargs
232        jso = json.loads(jsn) if isinstance(jsn, str) else jsn
233        ntv_value, = Ntv.decode_json(jso)[:1]
234
235        ntv_type = None
236        shape = None
237        match ntv_value[:-1]:
238            case []: ...
239            case [ntv_type, shape]: ...
240            case [str(ntv_type)]: ...
241            case [list(shape)]: ...
242        unidim = not shape is None
243        if isinstance(ntv_value[-1], str):
244            return Ndarray(ntv_value[-1], shape=shape, ntv_type=ntv_type)
245        darray = Darray.read_json(ntv_value[-1], dtype=Nutil.dtype(ntv_type),
246                                  unidim=unidim)
247        darray.data = Nutil.convert(ntv_type, darray.data, tojson=False,
248                                    convert=option['convert'])
249        return Ndarray(darray.values, shape=shape, ntv_type=ntv_type)
250
251    def to_json(self, **kwargs):
252        ''' convert a Ndarray into json-value
253
254        *Parameters*
255
256        - **noshape** : Boolean (default True) - if True, without shape if dim < 1
257        - **notype** : Boolean (default False) - including data type if False
258        - **novalue** : Boolean (default False) - including value if False
259        - **format** : string (default 'full') - representation format of the ndarray,
260        - **encoded** : Boolean (default False) - json-value if False else json-text
261        - **header** : Boolean (default True) - including ndarray type
262        '''
263        option = {'format': 'full', 'header': True, 'encoded': False,
264                  'notype': False, 'noshape': True, 'novalue': False} | kwargs
265        if self.mode in ['undefined', 'inconsistent']:
266            return None
267        if self.mode == 'absolute' and len(self.darray) == 0:
268            return [[]]
269
270        shape = None if not self.shape or (len(self.shape) < 2 and
271                                           option['noshape']) else self.shape
272
273        if self.mode == 'relative':
274            js_val = self.uri
275        else:
276            js_val = Nutil.ntv_val(self.ntv_type, self.darray, option['format'],
277                                   self.is_json) if not option['novalue'] else ['-']
278
279        lis = [self.ntv_type if not option['notype'] else None, shape, js_val]
280        return Nutil.json_ntv(None, 'ndarray',
281                              [val for val in lis if not val is None],
282                              header=option['header'], encoded=option['encoded'])
283
284    @property
285    def info(self):
286        ''' infos of the Ndarray'''
287        inf = {'shape': self.shape}
288        inf['length'] = len(self)
289        inf['ntvtype'] = self.ntv_type
290        inf['shape'] = self.shape
291        inf['uri'] = self.uri
292        return {key: val for key, val in inf.items() if val}
293
294    @staticmethod
295    def len_shape(shape):
296        '''return a length from a shape (product of dimensions)'''
297        if not shape:
298            return 0
299        prod = 1
300        for dim in shape:
301            prod *= dim
302        return prod

The Ndarray class is the JSON interface of numpy.ndarrays.

static methods

Ndarray(dar, ntv_type=None, shape=None)
37    def __init__(self, dar, ntv_type=None, shape=None):
38        '''Ndarray constructor.
39
40        *Parameters*
41
42        - **dar**: Darray or np.ndarray - data to represent
43        - **shape** : list of integer (default None) - length of dimensions
44        - **ntv_type**: string (default None) - NTVtype to apply
45        '''
46        dar = [None] if isinstance(dar, list) and len(dar) == 0 else dar
47        if isinstance(dar, Ndarray):
48            self.uri = dar.uri
49            self.is_json = dar.is_json
50            self.ntvtype = dar.ntvtype
51            self.shape = dar.shape
52            self.darray = dar.darray
53            return
54        if isinstance(dar, str):
55            self.uri = dar
56            self.is_json = True
57            self.ntvtype = Datatype(ntv_type) if ntv_type else None
58            self.shape = shape
59            self.darray = None
60            return
61        if shape:
62            dar = Dfull(dar, dtype=Nutil.dtype(ntv_type), unidim=True).data
63        else:
64            # dar = np.array(dar if isinstance(dar, (list, np.ndarray)) else [dar],
65            dar = np.array(dar, dtype=Nutil.dtype(ntv_type))
66            shape = list(dar.shape)
67        dar = np.array(dar).reshape(-1)
68        # ntv_type = Nutil.nda_ntv_type(dar) if not (ntv_type or dar is None) else ntv_type
69        ntv_type = Nutil.nda_ntv_type(dar, ntv_type)
70        self.uri = None
71        self.is_json = Nutil.is_json(dar[0])
72        self.ntvtype = Datatype(ntv_type)
73        self.shape = shape
74        self.darray = dar.astype(Nutil.dtype(str(self.ntvtype)))

Ndarray constructor.

Parameters

  • dar: Darray or np.ndarray - data to represent
  • shape : list of integer (default None) - length of dimensions
  • ntv_type: string (default None) - NTVtype to apply
uri
is_json
ntvtype
shape
darray
ntv_type
128    @property
129    def ntv_type(self):
130        ''' string representation of ntvtype'''
131        return str(self.ntvtype) if self.ntvtype else None

string representation of ntvtype

ndarray
133    @property
134    def ndarray(self):
135        '''representation with a np.ndarray not flattened'''
136        return self.darray.reshape(self.shape) if not self.darray is None else None

representation with a np.ndarray not flattened

def update(self, nda, nda_uri=True):
138    def update(self, nda, nda_uri=True):
139        '''update uri and darray and return the result (True, False)
140
141        *Parameters*
142
143        - **nda** : string, list, np.ndarray, Ndarray - data to include
144        - **nda_uri** : boolean (default True) - if True, existing shape and
145        ntv_type are not updated (but are created if not existing)'''
146        if not nda_uri and not (self.shape is None or nda.shape is None
147                                ) and self.shape != nda.shape:
148            return False
149        if not nda_uri and not (self.ntv_type is None or nda.ntv_type is None
150                                ) and self.ntv_type != nda.ntv_type:
151            return False
152        if nda_uri:
153            len_s = self.len_shape(self.shape)
154            if len_s and len(nda) and len_s != len(nda):
155                return False
156            self.ntvtype = nda.ntvtype if self.ntv_type is None else self.ntvtype
157            self.shape = nda.shape if self.shape is None else self.shape
158        else:
159            self.ntvtype = nda.ntvtype if not nda.ntv_type is None else self.ntvtype
160            self.shape = nda.shape if not nda.shape is None else self.shape
161        self.uri, self.darray = (
162            nda.uri, None) if nda.uri else (None, nda.darray)
163        return True

update uri and darray and return the result (True, False)

Parameters

  • nda : string, list, np.ndarray, Ndarray - data to include
  • nda_uri : boolean (default True) - if True, existing shape and ntv_type are not updated (but are created if not existing)
def set_array(self, darray):
165    def set_array(self, darray):
166        '''set a new darray and remove uri, return the result (True, False)
167
168        *Parameters*
169
170        - **darray** : list, np.ndarray, Ndarray - data to include'''
171        ndarray = Ndarray(darray)
172        darray = ndarray.darray
173        ntv_type = ndarray.ntv_type
174        shape = ndarray.shape
175        new_shape = shape if self.shape is None else self.shape
176        new_ntv_type = ntv_type if self.ntv_type is None else self.ntv_type
177        if (len(darray) != Ndarray.len_shape(new_shape) or
178                new_ntv_type != ntv_type or new_shape != shape):
179            return False
180        self.uri = None
181        self.darray = darray
182        self.ntvtype = Datatype(new_ntv_type)
183        self.shape = new_shape
184        return True

set a new darray and remove uri, return the result (True, False)

Parameters

  • darray : list, np.ndarray, Ndarray - data to include
def set_uri(self, uri, no_ntv_type=False, no_shape=False):
186    def set_uri(self, uri, no_ntv_type=False, no_shape=False):
187        '''set a new uri and remove ndarray and optionaly ntv_type and shape.
188        Return the result (True, False)
189
190        *Parameters*
191
192        - **uri** : string - URI of the Ndarray
193        - **no_ntv_type** : boolean (default False) - If True, ntv_type is None
194        - **no_shape** : boolean (default False) - If True, shape is None
195        '''
196        if not isinstance(uri, str) or not uri:
197            return False
198        self.uri = uri
199        self.darray = None
200        self.ntvtype = None if no_ntv_type else self.ntvtype
201        self.shape = None if no_shape else self.shape
202        return True

set a new uri and remove ndarray and optionaly ntv_type and shape. Return the result (True, False)

Parameters

  • uri : string - URI of the Ndarray
  • no_ntv_type : boolean (default False) - If True, ntv_type is None
  • no_shape : boolean (default False) - If True, shape is None
def to_ndarray(self):
204    def to_ndarray(self):
205        '''representation with a np.ndarray not flattened'''
206        return self.ndarray

representation with a np.ndarray not flattened

mode
208    @property
209    def mode(self):
210        '''representation mode of the darray/uri data (relative, absolute,
211        undefined, inconsistent)'''
212        match [self.darray, self.uri]:
213            case [None, str()]:
214                return 'relative'
215            case [None, None]:
216                return 'undefined'
217            case [_, None]:
218                return 'absolute'
219            case _:
220                return 'inconsistent'

representation mode of the darray/uri data (relative, absolute, undefined, inconsistent)

@staticmethod
def read_json(jsn, **kwargs):
222    @staticmethod
223    def read_json(jsn, **kwargs):
224        ''' convert json ntv_value into a ndarray.
225
226        *Parameters*
227
228        - **convert** : boolean (default True) - If True, convert json data with
229        non Numpy ntv_type into data with python type
230        '''
231        option = {'convert': True} | kwargs
232        jso = json.loads(jsn) if isinstance(jsn, str) else jsn
233        ntv_value, = Ntv.decode_json(jso)[:1]
234
235        ntv_type = None
236        shape = None
237        match ntv_value[:-1]:
238            case []: ...
239            case [ntv_type, shape]: ...
240            case [str(ntv_type)]: ...
241            case [list(shape)]: ...
242        unidim = not shape is None
243        if isinstance(ntv_value[-1], str):
244            return Ndarray(ntv_value[-1], shape=shape, ntv_type=ntv_type)
245        darray = Darray.read_json(ntv_value[-1], dtype=Nutil.dtype(ntv_type),
246                                  unidim=unidim)
247        darray.data = Nutil.convert(ntv_type, darray.data, tojson=False,
248                                    convert=option['convert'])
249        return Ndarray(darray.values, shape=shape, ntv_type=ntv_type)

convert json ntv_value into a ndarray.

Parameters

  • convert : boolean (default True) - If True, convert json data with non Numpy ntv_type into data with python type
def to_json(self, **kwargs):
251    def to_json(self, **kwargs):
252        ''' convert a Ndarray into json-value
253
254        *Parameters*
255
256        - **noshape** : Boolean (default True) - if True, without shape if dim < 1
257        - **notype** : Boolean (default False) - including data type if False
258        - **novalue** : Boolean (default False) - including value if False
259        - **format** : string (default 'full') - representation format of the ndarray,
260        - **encoded** : Boolean (default False) - json-value if False else json-text
261        - **header** : Boolean (default True) - including ndarray type
262        '''
263        option = {'format': 'full', 'header': True, 'encoded': False,
264                  'notype': False, 'noshape': True, 'novalue': False} | kwargs
265        if self.mode in ['undefined', 'inconsistent']:
266            return None
267        if self.mode == 'absolute' and len(self.darray) == 0:
268            return [[]]
269
270        shape = None if not self.shape or (len(self.shape) < 2 and
271                                           option['noshape']) else self.shape
272
273        if self.mode == 'relative':
274            js_val = self.uri
275        else:
276            js_val = Nutil.ntv_val(self.ntv_type, self.darray, option['format'],
277                                   self.is_json) if not option['novalue'] else ['-']
278
279        lis = [self.ntv_type if not option['notype'] else None, shape, js_val]
280        return Nutil.json_ntv(None, 'ndarray',
281                              [val for val in lis if not val is None],
282                              header=option['header'], encoded=option['encoded'])

convert a Ndarray into json-value

Parameters

  • noshape : Boolean (default True) - if True, without shape if dim < 1
  • notype : Boolean (default False) - including data type if False
  • novalue : Boolean (default False) - including value if False
  • format : string (default 'full') - representation format of the ndarray,
  • encoded : Boolean (default False) - json-value if False else json-text
  • header : Boolean (default True) - including ndarray type
info
284    @property
285    def info(self):
286        ''' infos of the Ndarray'''
287        inf = {'shape': self.shape}
288        inf['length'] = len(self)
289        inf['ntvtype'] = self.ntv_type
290        inf['shape'] = self.shape
291        inf['uri'] = self.uri
292        return {key: val for key, val in inf.items() if val}

infos of the Ndarray

@staticmethod
def len_shape(shape):
294    @staticmethod
295    def len_shape(shape):
296        '''return a length from a shape (product of dimensions)'''
297        if not shape:
298            return 0
299        prod = 1
300        for dim in shape:
301            prod *= dim
302        return prod

return a length from a shape (product of dimensions)

class Nutil:
305class Nutil:
306    '''ntv-ndarray utilities.
307
308    *static methods*
309    - `convert`
310    - `is_json`
311    - `ntv_val`
312    - `add_ext`
313    - `split_type`
314    - `ntv_type`
315    - `nda_ntv_type`
316    - `dtype`
317    - `json_ntv`
318    - `split_name`
319    - `split_json_name`
320
321    '''
322
323    DATATION_DT = {'date': 'datetime64[D]', 'year': 'datetime64[Y]',
324                   'yearmonth': 'datetime64[M]',
325                   'datetime': 'datetime64[s]', 'datetime[ms]': 'datetime64[ms]',
326                   'datetime[us]': 'datetime64[us]', 'datetime[ns]': 'datetime64[ns]',
327                   'datetime[ps]': 'datetime64[ps]', 'datetime[fs]': 'datetime64[fs]',
328                   'timedelta': 'timedelta64[s]', 'timedelta[ms]': 'timedelta64[ms]',
329                   'timedelta[us]': 'timedelta64[us]', 'timedelta[ns]': 'timedelta64[ns]',
330                   'timedelta[ps]': 'timedelta64[ps]', 'timedelta[fs]': 'timedelta64[fs]',
331                   'timedelta[D]': 'timedelta64[D]', 'timedelta[Y]': 'timedelta64[Y]',
332                   'timedelta[M]': 'timedelta64[M]'}
333    DT_DATATION = {val: key for key, val in DATATION_DT.items()}
334
335    # CONNECTOR_DT = {'field': 'Series', 'tab': 'DataFrame'}
336    CONNECTOR_DT = {'field': 'Series', 'tab': 'DataFrame'}
337    DT_CONNECTOR = {val: key for key, val in CONNECTOR_DT.items()}
338
339    PYTHON_DT = {'array': 'list', 'time': 'datetime.time',
340                 'object': 'dict', 'null': 'NoneType', 'decimal64': 'Decimal',
341                 'ndarray': 'ndarray', 'narray': 'narray'}
342    DT_PYTHON = {val: key for key, val in PYTHON_DT.items()}
343
344    # OTHER_DT = {'boolean': 'bool', 'string': 'str'}
345    OTHER_DT = {'boolean': 'bool', 'string': 'str', 'base16': 'bytes'}
346    DT_OTHER = {val: key for key, val in OTHER_DT.items()}
347
348    LOCATION_DT = {'point': 'Point',
349                   'line': 'LineString', 'polygon': 'Polygon'}
350    DT_LOCATION = {val: key for key, val in LOCATION_DT.items()}
351
352    NUMBER_DT = {'json': 'object', 'number': None, 'month': 'int', 'day': 'int',
353                 'wday': 'int', 'yday': 'int', 'week': 'hour', 'minute': 'int',
354                 'second': 'int'}
355    # STRING_DT = {'base16': 'str', 'base32': 'str', 'base64': 'str',
356    STRING_DT = {'base32': 'str', 'base64': 'str',
357                 'period': 'str', 'duration': 'str', 'jpointer': 'str',
358                 'uri': 'str', 'uriref': 'str', 'iri': 'str', 'iriref': 'str',
359                 'email': 'str', 'regex': 'str', 'hostname': 'str', 'ipv4': 'str',
360                 'ipv6': 'str', 'file': 'str', 'geojson': 'str', }
361    FORMAT_CLS = {'full': Dfull, 'complete': Dcomplete}
362    CONVERT_DT = {'object': 'object', 'array': 'object', 'json': 'object',
363                  'number': 'float', 'boolean': 'bool', 'null': 'object',
364                  'string': 'str', 'integer': 'int'}
365    STRUCT_DT = {'Ntv': 'object', 'NtvSingle': 'object', 'NtvList': 'object'}
366
367    DT_NTVTYPE = DT_DATATION | DT_LOCATION | DT_OTHER | DT_CONNECTOR | DT_PYTHON
368
369    @staticmethod
370    def is_json(obj):
371        ''' check if obj is a json structure and return True if obj is a json-value
372
373        *Parameters*
374
375        - **obj** : object to check'''
376        if obj is None:
377            return True
378        is_js = NtvConnector.is_json
379        match obj:
380            case str() | int() | float() | bool():
381                return True
382            case list() | tuple() as obj:
383                if not obj:
384                    return True
385                return min(is_js(obj_in) for obj_in in obj)
386            case dict() as obj:
387                if not obj:
388                    return True
389                if not min(isinstance(key, str) for key in obj.keys()):
390                    return False
391                return min(is_js(obj_in) for obj_in in obj.values())
392            case _:
393                return False
394
395    @staticmethod
396    def convert(ntv_type, nda, tojson=True, convert=True):
397        ''' convert np.ndarray with external NTVtype.
398
399        *Parameters*
400
401        - **ntv_type** : string - NTVtype deduced from the np.ndarray name_type and dtype,
402        - **nda** : np.ndarray to be converted.
403        - **tojson** : boolean (default True) - apply to json function
404        - **convert** : boolean (default True) - If True, convert json data with
405        non Numpy ntv_type into data with python type
406        '''
407        if tojson:
408            match ntv_type:
409                case dat if dat in Nutil.DATATION_DT:
410                    return nda.astype(Nutil.DATATION_DT[dat]).astype(str)
411                case 'bytes':
412                    return nda.astype('bytes').astype(str)
413                case 'time':
414                    return nda.astype(str)
415                case 'decimal64':
416                    return nda.astype(float)
417                case 'geojson':
418                    return np.frompyfunc(ShapelyConnec.to_geojson, 1, 1)(nda)
419                case _:
420                    return nda
421        else:
422            match [ntv_type, convert]:
423                case [None, _]:
424                    return nda
425                case [dat, _] if dat in Nutil.DATATION_DT:
426                    return nda.astype(Nutil.DATATION_DT[dat])
427                case [std, _] if std in Nutil.OTHER_DT:
428                    return nda.astype(Nutil.OTHER_DT[std])
429                case ['time', True]:
430                    return np.frompyfunc(datetime.time.fromisoformat, 1, 1)(nda)
431                case ['decimal64', True]:
432                    return np.frompyfunc(Decimal, 1, 1)(nda)
433                case ['narray', True]:
434                    nar = np.frompyfunc(Ndarray.read_json, 1, 1)(nda)
435                    return np.frompyfunc(Ndarray.to_ndarray, 1, 1)(nar)
436                case ['ndarray', True]:
437                    return np.frompyfunc(Ndarray.read_json, 1, 1)(nda)
438                case [python, _] if python in Nutil.PYTHON_DT:
439                    return nda.astype('object')
440                case [connec, True] if connec in Nutil.CONNECTOR_DT:
441                    return np.fromiter([NtvConnector.uncast(nd, None, connec)[0]
442                                        for nd in nda], dtype='object')
443                case [('point' | 'line' | 'polygon' | 'geometry'), True]:
444                    return np.frompyfunc(ShapelyConnec.to_geometry, 1, 1)(nda)
445                case [_, False]:
446                    return nda.astype(Nutil.CONVERT_DT[
447                        Nutil.dtype(ntv_type, convert=False)])
448                case _:
449                    return nda.astype(Nutil.dtype(ntv_type))
450
451        # float.fromhex(x.hex()) == x, bytes(bytearray.fromhex(x.hex())) == x
452    @staticmethod
453    def ntv_val(ntv_type, nda, form, is_json=False):
454        ''' convert a np.ndarray into NTV json-value.
455
456        *Parameters*
457
458        - **ntv_type** : string - NTVtype deduced from the ndarray, name_type and dtype,
459        - **nda** : ndarray to be converted.
460        - **form** : format of data ('full', 'complete', 'sparse', 'primary').
461        - **is_json** : boolean (defaut False) - True if nda data is Json data
462        '''
463        if form == 'complete' and len(nda) < 2:
464            raise NdarrayError(
465                "complete format is not available with ndarray length < 2")
466        Format = Nutil.FORMAT_CLS[form]
467        darray = Format(nda)
468        ref = darray.ref
469        coding = darray.coding
470        if is_json:
471            return Format(darray.data, ref=ref, coding=coding).to_json()
472        match ntv_type:
473            case 'narray':
474                data = [Ndarray(nd).to_json(header=False)
475                        for nd in darray.data]
476            case 'ndarray':
477                # data = [Ndarray.to_json(nd) for nd in darray.data]
478                data = [Ndarray(nd).to_json(header=False)
479                        for nd in darray.data]
480            case connec if connec in Nutil.CONNECTOR_DT:
481                data = [NtvConnector.cast(nd, None, connec)[0]
482                        for nd in darray.data]
483            case 'point' | 'line' | 'polygon' | 'geometry':
484                data = np.frompyfunc(ShapelyConnec.to_coord, 1, 1)(darray.data)
485            case None:
486                data = nda
487            case _:
488                data = Nutil.convert(ntv_type, darray.data)
489        return Format(data, ref=ref, coding=coding).to_json()
490
491    @staticmethod
492    def add_ext(typ, ext):
493        '''return extended type : "typ[ext]"'''
494        ext = '[' + ext + ']' if ext else ''
495        return '' if not typ else typ + ext
496
497    @staticmethod
498    def split_type(typ):
499        '''return a tuple with typ and extension'''
500        if not isinstance(typ, str):
501            return (None, None)
502        spl = typ.split('[', maxsplit=1)
503        return (spl[0], None) if len(spl) == 1 else (spl[0], spl[1][:-1])
504
505    @staticmethod
506    def split_json_name(string, notnone=False):
507        '''return a tuple with name, ntv_type from string'''
508        null = '' if notnone else None
509        if not string or string == ':':
510            return (null, null)
511        spl = string.rsplit(':', maxsplit=1)
512        if len(spl) == 1:
513            return (string, null)
514        if spl[0] == '':
515            return (null, spl[1])
516        sp0 = spl[0][:-1] if spl[0][-1] == ':' else spl[0]
517        return (null if sp0 == '' else sp0, null if spl[1] == '' else spl[1])
518
519    @staticmethod
520    def split_name(string):
521        '''return a list with name, add_name from string'''
522        if not string or string == '.':
523            return ['', '']
524        spl = string.split('.', maxsplit=1)
525        spl = [spl[0], ''] if len(spl) < 2 else spl
526        return spl
527
528    @staticmethod
529    def ntv_type(dtype, ntv_type=None, ext=None):
530        ''' return NTVtype from dtype, additional type and extension.
531
532        *Parameters*
533
534        - **dtype** : string - dtype of the ndarray
535        - **ntv_type** : string - additional type
536        - **ext** : string - type extension
537        '''
538        if ntv_type:
539            return Nutil.add_ext(ntv_type, ext)
540        match dtype:
541            case dat if dat in Nutil.DT_NTVTYPE:
542                return Nutil.add_ext(Nutil.DT_NTVTYPE[dat], ext)
543            case string if string[:3] == 'str':
544                return Nutil.add_ext('string', ext)
545            case byte if byte[:5] == 'bytes':
546                # return Nutil.add_ext('bytes', ext)
547                return Nutil.add_ext('base16', ext)
548            case _:
549                return Nutil.add_ext(dtype, ext)
550
551    @staticmethod
552    def nda_ntv_type(nda, ntv_type=None, ext=None):
553        '''return ntv_type from an ndarray, additional type and extension.
554
555        *Parameters*
556
557        - **nda** : ndarray - data used to calculate the ntv_type
558        - **ntv_type** : string - additional type
559        - **ext** : string - type extension
560        '''
561        if ntv_type or nda is None:
562            return ntv_type
563        dtype = nda.dtype.name
564        pytype = nda.flat[0].__class__.__name__
565        dtype = pytype if dtype == 'object' and not pytype in Nutil.STRUCT_DT else dtype
566        # dtype = pytype if dtype == 'object' and pytype in Nutil.DT_NTVTYPE else dtype
567        # dtype = nda.flat[0].__class__.__name__ if dtype == 'object' else dtype
568        return Nutil.ntv_type(dtype, ntv_type, ext)
569
570    @staticmethod
571    def dtype(ntv_type, convert=True):
572        ''' return dtype from ntv_type
573
574        *parameters*
575
576        - **convert** : boolean (default True) - if True, dtype if from converted data
577        '''
578        DTYPE = (Nutil.DATATION_DT | Nutil.NUMBER_DT | Nutil.OTHER_DT |
579                 Nutil.STRING_DT)
580        OBJECT = Nutil.LOCATION_DT | Nutil.CONNECTOR_DT | Nutil.PYTHON_DT
581        type_base = Nutil.split_type(ntv_type)[0]
582        if convert:
583            if type_base in OBJECT:
584                return 'object'
585            return DTYPE.get(ntv_type, DTYPE.get(type_base, type_base))
586        return Datatype(ntv_type).json_type
587
588    @staticmethod
589    def json_ntv(ntv_name, ntv_type, ntv_value, **kwargs):
590        ''' return the JSON representation of a NTV entity
591
592        *parameters*
593
594        - **ntv_name** : string - name of the NTV
595        - **ntv_type** : string - type of the NTV
596        - **ntv_value** : string - Json value of the NTV
597        - **encoded** : boolean (default False) - if True return JsonText else JsonValue
598        - **header** : boolean (default True) - if True include ntv_name + ntv_type
599        '''
600        name = ntv_name if ntv_name else ''
601        option = {'encoded': False, 'header': True} | kwargs
602        if option['header'] or name:
603            typ = ':' + ntv_type if option['header'] and ntv_type else ''
604            jsn = {name + typ: ntv_value} if name + typ else ntv_value
605        else:
606            jsn = ntv_value
607        if option['encoded']:
608            return json.dumps(jsn)
609        return jsn
DATATION_DT = {'date': 'datetime64[D]', 'year': 'datetime64[Y]', 'yearmonth': 'datetime64[M]', 'datetime': 'datetime64[s]', 'datetime[ms]': 'datetime64[ms]', 'datetime[us]': 'datetime64[us]', 'datetime[ns]': 'datetime64[ns]', 'datetime[ps]': 'datetime64[ps]', 'datetime[fs]': 'datetime64[fs]', 'timedelta': 'timedelta64[s]', 'timedelta[ms]': 'timedelta64[ms]', 'timedelta[us]': 'timedelta64[us]', 'timedelta[ns]': 'timedelta64[ns]', 'timedelta[ps]': 'timedelta64[ps]', 'timedelta[fs]': 'timedelta64[fs]', 'timedelta[D]': 'timedelta64[D]', 'timedelta[Y]': 'timedelta64[Y]', 'timedelta[M]': 'timedelta64[M]'}
DT_DATATION = {'datetime64[D]': 'date', 'datetime64[Y]': 'year', 'datetime64[M]': 'yearmonth', 'datetime64[s]': 'datetime', 'datetime64[ms]': 'datetime[ms]', 'datetime64[us]': 'datetime[us]', 'datetime64[ns]': 'datetime[ns]', 'datetime64[ps]': 'datetime[ps]', 'datetime64[fs]': 'datetime[fs]', 'timedelta64[s]': 'timedelta', 'timedelta64[ms]': 'timedelta[ms]', 'timedelta64[us]': 'timedelta[us]', 'timedelta64[ns]': 'timedelta[ns]', 'timedelta64[ps]': 'timedelta[ps]', 'timedelta64[fs]': 'timedelta[fs]', 'timedelta64[D]': 'timedelta[D]', 'timedelta64[Y]': 'timedelta[Y]', 'timedelta64[M]': 'timedelta[M]'}
CONNECTOR_DT = {'field': 'Series', 'tab': 'DataFrame'}
DT_CONNECTOR = {'Series': 'field', 'DataFrame': 'tab'}
PYTHON_DT = {'array': 'list', 'time': 'datetime.time', 'object': 'dict', 'null': 'NoneType', 'decimal64': 'Decimal', 'ndarray': 'ndarray', 'narray': 'narray'}
DT_PYTHON = {'list': 'array', 'datetime.time': 'time', 'dict': 'object', 'NoneType': 'null', 'Decimal': 'decimal64', 'ndarray': 'ndarray', 'narray': 'narray'}
OTHER_DT = {'boolean': 'bool', 'string': 'str', 'base16': 'bytes'}
DT_OTHER = {'bool': 'boolean', 'str': 'string', 'bytes': 'base16'}
LOCATION_DT = {'point': 'Point', 'line': 'LineString', 'polygon': 'Polygon'}
DT_LOCATION = {'Point': 'point', 'LineString': 'line', 'Polygon': 'polygon'}
NUMBER_DT = {'json': 'object', 'number': None, 'month': 'int', 'day': 'int', 'wday': 'int', 'yday': 'int', 'week': 'hour', 'minute': 'int', 'second': 'int'}
STRING_DT = {'base32': 'str', 'base64': 'str', 'period': 'str', 'duration': 'str', 'jpointer': 'str', 'uri': 'str', 'uriref': 'str', 'iri': 'str', 'iriref': 'str', 'email': 'str', 'regex': 'str', 'hostname': 'str', 'ipv4': 'str', 'ipv6': 'str', 'file': 'str', 'geojson': 'str'}
FORMAT_CLS = {'full': <class 'ntv_numpy.data_array.Dfull'>, 'complete': <class 'ntv_numpy.data_array.Dcomplete'>}
CONVERT_DT = {'object': 'object', 'array': 'object', 'json': 'object', 'number': 'float', 'boolean': 'bool', 'null': 'object', 'string': 'str', 'integer': 'int'}
STRUCT_DT = {'Ntv': 'object', 'NtvSingle': 'object', 'NtvList': 'object'}
DT_NTVTYPE = {'datetime64[D]': 'date', 'datetime64[Y]': 'year', 'datetime64[M]': 'yearmonth', 'datetime64[s]': 'datetime', 'datetime64[ms]': 'datetime[ms]', 'datetime64[us]': 'datetime[us]', 'datetime64[ns]': 'datetime[ns]', 'datetime64[ps]': 'datetime[ps]', 'datetime64[fs]': 'datetime[fs]', 'timedelta64[s]': 'timedelta', 'timedelta64[ms]': 'timedelta[ms]', 'timedelta64[us]': 'timedelta[us]', 'timedelta64[ns]': 'timedelta[ns]', 'timedelta64[ps]': 'timedelta[ps]', 'timedelta64[fs]': 'timedelta[fs]', 'timedelta64[D]': 'timedelta[D]', 'timedelta64[Y]': 'timedelta[Y]', 'timedelta64[M]': 'timedelta[M]', 'Point': 'point', 'LineString': 'line', 'Polygon': 'polygon', 'bool': 'boolean', 'str': 'string', 'bytes': 'base16', 'Series': 'field', 'DataFrame': 'tab', 'list': 'array', 'datetime.time': 'time', 'dict': 'object', 'NoneType': 'null', 'Decimal': 'decimal64', 'ndarray': 'ndarray', 'narray': 'narray'}
@staticmethod
def is_json(obj):
369    @staticmethod
370    def is_json(obj):
371        ''' check if obj is a json structure and return True if obj is a json-value
372
373        *Parameters*
374
375        - **obj** : object to check'''
376        if obj is None:
377            return True
378        is_js = NtvConnector.is_json
379        match obj:
380            case str() | int() | float() | bool():
381                return True
382            case list() | tuple() as obj:
383                if not obj:
384                    return True
385                return min(is_js(obj_in) for obj_in in obj)
386            case dict() as obj:
387                if not obj:
388                    return True
389                if not min(isinstance(key, str) for key in obj.keys()):
390                    return False
391                return min(is_js(obj_in) for obj_in in obj.values())
392            case _:
393                return False

check if obj is a json structure and return True if obj is a json-value

Parameters

  • obj : object to check
@staticmethod
def convert(ntv_type, nda, tojson=True, convert=True):
395    @staticmethod
396    def convert(ntv_type, nda, tojson=True, convert=True):
397        ''' convert np.ndarray with external NTVtype.
398
399        *Parameters*
400
401        - **ntv_type** : string - NTVtype deduced from the np.ndarray name_type and dtype,
402        - **nda** : np.ndarray to be converted.
403        - **tojson** : boolean (default True) - apply to json function
404        - **convert** : boolean (default True) - If True, convert json data with
405        non Numpy ntv_type into data with python type
406        '''
407        if tojson:
408            match ntv_type:
409                case dat if dat in Nutil.DATATION_DT:
410                    return nda.astype(Nutil.DATATION_DT[dat]).astype(str)
411                case 'bytes':
412                    return nda.astype('bytes').astype(str)
413                case 'time':
414                    return nda.astype(str)
415                case 'decimal64':
416                    return nda.astype(float)
417                case 'geojson':
418                    return np.frompyfunc(ShapelyConnec.to_geojson, 1, 1)(nda)
419                case _:
420                    return nda
421        else:
422            match [ntv_type, convert]:
423                case [None, _]:
424                    return nda
425                case [dat, _] if dat in Nutil.DATATION_DT:
426                    return nda.astype(Nutil.DATATION_DT[dat])
427                case [std, _] if std in Nutil.OTHER_DT:
428                    return nda.astype(Nutil.OTHER_DT[std])
429                case ['time', True]:
430                    return np.frompyfunc(datetime.time.fromisoformat, 1, 1)(nda)
431                case ['decimal64', True]:
432                    return np.frompyfunc(Decimal, 1, 1)(nda)
433                case ['narray', True]:
434                    nar = np.frompyfunc(Ndarray.read_json, 1, 1)(nda)
435                    return np.frompyfunc(Ndarray.to_ndarray, 1, 1)(nar)
436                case ['ndarray', True]:
437                    return np.frompyfunc(Ndarray.read_json, 1, 1)(nda)
438                case [python, _] if python in Nutil.PYTHON_DT:
439                    return nda.astype('object')
440                case [connec, True] if connec in Nutil.CONNECTOR_DT:
441                    return np.fromiter([NtvConnector.uncast(nd, None, connec)[0]
442                                        for nd in nda], dtype='object')
443                case [('point' | 'line' | 'polygon' | 'geometry'), True]:
444                    return np.frompyfunc(ShapelyConnec.to_geometry, 1, 1)(nda)
445                case [_, False]:
446                    return nda.astype(Nutil.CONVERT_DT[
447                        Nutil.dtype(ntv_type, convert=False)])
448                case _:
449                    return nda.astype(Nutil.dtype(ntv_type))
450
451        # float.fromhex(x.hex()) == x, bytes(bytearray.fromhex(x.hex())) == x

convert np.ndarray with external NTVtype.

Parameters

  • ntv_type : string - NTVtype deduced from the np.ndarray name_type and dtype,
  • nda : np.ndarray to be converted.
  • tojson : boolean (default True) - apply to json function
  • convert : boolean (default True) - If True, convert json data with non Numpy ntv_type into data with python type
@staticmethod
def ntv_val(ntv_type, nda, form, is_json=False):
452    @staticmethod
453    def ntv_val(ntv_type, nda, form, is_json=False):
454        ''' convert a np.ndarray into NTV json-value.
455
456        *Parameters*
457
458        - **ntv_type** : string - NTVtype deduced from the ndarray, name_type and dtype,
459        - **nda** : ndarray to be converted.
460        - **form** : format of data ('full', 'complete', 'sparse', 'primary').
461        - **is_json** : boolean (defaut False) - True if nda data is Json data
462        '''
463        if form == 'complete' and len(nda) < 2:
464            raise NdarrayError(
465                "complete format is not available with ndarray length < 2")
466        Format = Nutil.FORMAT_CLS[form]
467        darray = Format(nda)
468        ref = darray.ref
469        coding = darray.coding
470        if is_json:
471            return Format(darray.data, ref=ref, coding=coding).to_json()
472        match ntv_type:
473            case 'narray':
474                data = [Ndarray(nd).to_json(header=False)
475                        for nd in darray.data]
476            case 'ndarray':
477                # data = [Ndarray.to_json(nd) for nd in darray.data]
478                data = [Ndarray(nd).to_json(header=False)
479                        for nd in darray.data]
480            case connec if connec in Nutil.CONNECTOR_DT:
481                data = [NtvConnector.cast(nd, None, connec)[0]
482                        for nd in darray.data]
483            case 'point' | 'line' | 'polygon' | 'geometry':
484                data = np.frompyfunc(ShapelyConnec.to_coord, 1, 1)(darray.data)
485            case None:
486                data = nda
487            case _:
488                data = Nutil.convert(ntv_type, darray.data)
489        return Format(data, ref=ref, coding=coding).to_json()

convert a np.ndarray into NTV json-value.

Parameters

  • ntv_type : string - NTVtype deduced from the ndarray, name_type and dtype,
  • nda : ndarray to be converted.
  • form : format of data ('full', 'complete', 'sparse', 'primary').
  • is_json : boolean (defaut False) - True if nda data is Json data
@staticmethod
def add_ext(typ, ext):
491    @staticmethod
492    def add_ext(typ, ext):
493        '''return extended type : "typ[ext]"'''
494        ext = '[' + ext + ']' if ext else ''
495        return '' if not typ else typ + ext

return extended type : "typ[ext]"

@staticmethod
def split_type(typ):
497    @staticmethod
498    def split_type(typ):
499        '''return a tuple with typ and extension'''
500        if not isinstance(typ, str):
501            return (None, None)
502        spl = typ.split('[', maxsplit=1)
503        return (spl[0], None) if len(spl) == 1 else (spl[0], spl[1][:-1])

return a tuple with typ and extension

@staticmethod
def split_json_name(string, notnone=False):
505    @staticmethod
506    def split_json_name(string, notnone=False):
507        '''return a tuple with name, ntv_type from string'''
508        null = '' if notnone else None
509        if not string or string == ':':
510            return (null, null)
511        spl = string.rsplit(':', maxsplit=1)
512        if len(spl) == 1:
513            return (string, null)
514        if spl[0] == '':
515            return (null, spl[1])
516        sp0 = spl[0][:-1] if spl[0][-1] == ':' else spl[0]
517        return (null if sp0 == '' else sp0, null if spl[1] == '' else spl[1])

return a tuple with name, ntv_type from string

@staticmethod
def split_name(string):
519    @staticmethod
520    def split_name(string):
521        '''return a list with name, add_name from string'''
522        if not string or string == '.':
523            return ['', '']
524        spl = string.split('.', maxsplit=1)
525        spl = [spl[0], ''] if len(spl) < 2 else spl
526        return spl

return a list with name, add_name from string

@staticmethod
def ntv_type(dtype, ntv_type=None, ext=None):
528    @staticmethod
529    def ntv_type(dtype, ntv_type=None, ext=None):
530        ''' return NTVtype from dtype, additional type and extension.
531
532        *Parameters*
533
534        - **dtype** : string - dtype of the ndarray
535        - **ntv_type** : string - additional type
536        - **ext** : string - type extension
537        '''
538        if ntv_type:
539            return Nutil.add_ext(ntv_type, ext)
540        match dtype:
541            case dat if dat in Nutil.DT_NTVTYPE:
542                return Nutil.add_ext(Nutil.DT_NTVTYPE[dat], ext)
543            case string if string[:3] == 'str':
544                return Nutil.add_ext('string', ext)
545            case byte if byte[:5] == 'bytes':
546                # return Nutil.add_ext('bytes', ext)
547                return Nutil.add_ext('base16', ext)
548            case _:
549                return Nutil.add_ext(dtype, ext)

return NTVtype from dtype, additional type and extension.

Parameters

  • dtype : string - dtype of the ndarray
  • ntv_type : string - additional type
  • ext : string - type extension
@staticmethod
def nda_ntv_type(nda, ntv_type=None, ext=None):
551    @staticmethod
552    def nda_ntv_type(nda, ntv_type=None, ext=None):
553        '''return ntv_type from an ndarray, additional type and extension.
554
555        *Parameters*
556
557        - **nda** : ndarray - data used to calculate the ntv_type
558        - **ntv_type** : string - additional type
559        - **ext** : string - type extension
560        '''
561        if ntv_type or nda is None:
562            return ntv_type
563        dtype = nda.dtype.name
564        pytype = nda.flat[0].__class__.__name__
565        dtype = pytype if dtype == 'object' and not pytype in Nutil.STRUCT_DT else dtype
566        # dtype = pytype if dtype == 'object' and pytype in Nutil.DT_NTVTYPE else dtype
567        # dtype = nda.flat[0].__class__.__name__ if dtype == 'object' else dtype
568        return Nutil.ntv_type(dtype, ntv_type, ext)

return ntv_type from an ndarray, additional type and extension.

Parameters

  • nda : ndarray - data used to calculate the ntv_type
  • ntv_type : string - additional type
  • ext : string - type extension
@staticmethod
def dtype(ntv_type, convert=True):
570    @staticmethod
571    def dtype(ntv_type, convert=True):
572        ''' return dtype from ntv_type
573
574        *parameters*
575
576        - **convert** : boolean (default True) - if True, dtype if from converted data
577        '''
578        DTYPE = (Nutil.DATATION_DT | Nutil.NUMBER_DT | Nutil.OTHER_DT |
579                 Nutil.STRING_DT)
580        OBJECT = Nutil.LOCATION_DT | Nutil.CONNECTOR_DT | Nutil.PYTHON_DT
581        type_base = Nutil.split_type(ntv_type)[0]
582        if convert:
583            if type_base in OBJECT:
584                return 'object'
585            return DTYPE.get(ntv_type, DTYPE.get(type_base, type_base))
586        return Datatype(ntv_type).json_type

return dtype from ntv_type

parameters

  • convert : boolean (default True) - if True, dtype if from converted data
@staticmethod
def json_ntv(ntv_name, ntv_type, ntv_value, **kwargs):
588    @staticmethod
589    def json_ntv(ntv_name, ntv_type, ntv_value, **kwargs):
590        ''' return the JSON representation of a NTV entity
591
592        *parameters*
593
594        - **ntv_name** : string - name of the NTV
595        - **ntv_type** : string - type of the NTV
596        - **ntv_value** : string - Json value of the NTV
597        - **encoded** : boolean (default False) - if True return JsonText else JsonValue
598        - **header** : boolean (default True) - if True include ntv_name + ntv_type
599        '''
600        name = ntv_name if ntv_name else ''
601        option = {'encoded': False, 'header': True} | kwargs
602        if option['header'] or name:
603            typ = ':' + ntv_type if option['header'] and ntv_type else ''
604            jsn = {name + typ: ntv_value} if name + typ else ntv_value
605        else:
606            jsn = ntv_value
607        if option['encoded']:
608            return json.dumps(jsn)
609        return jsn

return the JSON representation of a NTV entity

parameters

  • ntv_name : string - name of the NTV
  • ntv_type : string - type of the NTV
  • ntv_value : string - Json value of the NTV
  • encoded : boolean (default False) - if True return JsonText else JsonValue
  • header : boolean (default True) - if True include ntv_name + ntv_type
class NdarrayError(builtins.Exception):
612class NdarrayError(Exception):
613    '''Multidimensional exception'''

Multidimensional exception

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
add_note
args