ntv-numpy.ntv_numpy.xndarray
@author: Philippe@loco-labs.io
The xndarray
module is part of the ntv-numpy.ntv_numpy
package (specification document).
It contains the classes Xndarray
for the labeled multidimensional array.
For more information, see the user guide or the github repository.
1# -*- coding: utf-8 -*- 2""" 3@author: Philippe@loco-labs.io 4 5The `xndarray` 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 `Xndarray` for the labeled multidimensional array. 9 10For more information, see the 11[user guide](https://loco-philippe.github.io/ntv-numpy/docs/user_guide.html) 12 or the [github repository](https://github.com/loco-philippe/ntv-numpy). 13""" 14 15import json 16from json_ntv import Ntv 17from ntv_numpy.ndarray import Ndarray, Nutil, NdarrayError 18 19 20class Xndarray: 21 ''' Representation of a labelled multidimensional Array 22 23 *Attributes :* 24 - **name** : string - name of the Xndarray 25 - **add_name** : string - additional name of the Xndarray 26 - **nda**: Ndarray - ndarray data 27 - **links**: list of string - links to other Xndarray 28 - **meta** : JsonValue - informations 29 30 *dynamic values (@property)* 31 - `darray` 32 - `ndarray` 33 - `uri` 34 - `shape` 35 - `ntv_type` 36 - `info` 37 - `mode` 38 - `xtype` 39 - `full_name` 40 - `json_name` 41 42 *methods* 43 - `to_json` 44 - `read_json (static method)` 45 - `set_ndarray` 46 ''' 47 48 def __init__(self, full_name, nda=None, links=None, 49 meta=None): 50 '''Xndarray constructor. 51 52 *Parameters* 53 54 - **full_name**: string (default None) - name with additional name 55 - **nda** : Ndarray (default None) - data 56 - **links**: List of string (default None) - dims or other names of associated Xndarray 57 - **ntv_type**: string (default None) - ntv_type to apply to data 58 - **meta**: dict (default None) - information 59 ''' 60 if isinstance(full_name, Xndarray): 61 self.name = full_name.name 62 self.add_name = full_name.add_name 63 self.nda = full_name.nda 64 self.links = full_name.links 65 self.meta = full_name.meta 66 return 67 self.name, self.add_name = Nutil.split_name(full_name) 68 self.nda = Ndarray(nda) if not nda is None else None 69 self.links = links if links else None 70 self.meta = meta if meta else None 71 if self.meta is None and self.nda is None: 72 raise NdarrayError('A Xndarray has to have metadata or Ndarray') 73 74 def __repr__(self): 75 '''return classname and number of value''' 76 return self.__class__.__name__ + '[' + self.full_name + ']' 77 78 def __str__(self): 79 '''return json string format''' 80 return json.dumps(self.to_json()) 81 82 def __eq__(self, other): 83 ''' equal if attributes are equal''' 84 if self.name != other.name or self.add_name != other.add_name: 85 return False 86 if self.links != other.links or self.meta != other.meta: 87 return False 88 if self.nda is None and other.nda is None: 89 return True 90 if self.nda is None or other.nda is None: 91 return False 92 return self.nda == other.nda 93 94 def __len__(self): 95 ''' len of ndarray''' 96 return len(self.nda) if self.nda is not None else 0 97 98 def __contains__(self, item): 99 ''' item of ndarray values''' 100 return item in self.nda if self.nda is not None else None 101 102 def __getitem__(self, ind): 103 ''' return ndarray value item''' 104 if self.nda is None: 105 return None 106 if isinstance(ind, tuple): 107 return [self.nda[i] for i in ind] 108 return self.nda[ind] 109 110 def __copy__(self): 111 ''' Copy all the data ''' 112 return self.__class__(self) 113 114 @property 115 def darray(self): 116 '''return the darray of the ndarray''' 117 return self.nda.darray if self.nda is not None else None 118 119 @property 120 def ndarray(self): 121 '''return the darray of the ndarray''' 122 return self.nda.ndarray if self.nda is not None else None 123 124 @property 125 def uri(self): 126 '''return the uri of the ndarray''' 127 return self.nda.uri if self.nda is not None else None 128 129 @property 130 def shape(self): 131 '''return the shape of the ndarray''' 132 return self.nda.shape if self.nda is not None else None 133 134 @property 135 def ntv_type(self): 136 '''return the ntv_type of the ndarray''' 137 return self.nda.ntv_type if self.nda is not None else None 138 139 @property 140 def mode(self): 141 '''return the mode of the ndarray''' 142 return self.nda.mode if self.nda is not None else 'undefined' 143 144 @property 145 def info(self): 146 ''' infos of the Xndarray''' 147 inf = {'name': self.full_name} 148 inf['length'] = len(self) 149 if self.nda: 150 inf['mode'] = self.mode 151 inf['ntvtype'] = self.ntv_type 152 inf['shape'] = self.shape 153 inf['uri'] = self.uri 154 inf['meta'] = self.meta 155 inf['xtype'] = self.xtype 156 inf['links'] = self.links 157 return {key: val for key, val in inf.items() if val} 158 159 @property 160 def xtype(self): 161 '''nature of the Xndarray (undefined, namedarray, variable, additional, 162 meta, inconsistent)''' 163 match [self.links, self.add_name, self.mode]: 164 case [_, _, 'inconsistent']: 165 return 'inconsistent' 166 case [_, _, 'undefined']: 167 return 'meta' 168 case [None, '', _]: 169 return 'namedarray' 170 case [_, '', _]: 171 return 'variable' 172 case [_, str(), _]: 173 return 'additional' 174 case _: 175 return 'inconsistent' 176 177 @property 178 def full_name(self): 179 '''concatenation of name and additional name''' 180 add_name = '.' + self.add_name if self.add_name else '' 181 return self.name + add_name 182 183 @property 184 def json_name(self): 185 '''concatenation of full_name and ntv_type''' 186 add_ntv_type = ':' + self.ntv_type if self.ntv_type else '' 187 return self.full_name + add_ntv_type 188 189 @staticmethod 190 def read_json(jsn, **kwargs): 191 ''' convert json data into a Xndarray. 192 193 *Parameters* 194 195 - **convert** : boolean (default True) - If True, convert json data with 196 non Numpy ntv_type into data with python type 197 ''' 198 option = {'convert': True} | kwargs 199 jso = json.loads(jsn) if isinstance(jsn, str) else jsn 200 value, full_name = Ntv.decode_json(jso)[:2] 201 202 meta = links = nda = None 203 match value: 204 case str(meta) | dict(meta): ... 205 case [list(nda)]: ... 206 case [list(nda), list(links)]: ... 207 case [list(nda), dict(meta)] | [list(nda), str(meta)]: ... 208 case [list(nda), list(links), dict(meta)]: ... 209 case [list(nda), list(links), str(meta)]: ... 210 case _: 211 return None 212 nda = Ndarray.read_json(nda, **option) if nda else None 213 return Xndarray(full_name, links=links, meta=meta, nda=nda) 214 215 def set_ndarray(self, ndarray, nda_uri=True): 216 '''set a new ndarray (nda) and return the result (True, False) 217 218 *Parameters* 219 220 - **ndarray** : string, list, np.ndarray, Ndarray - data to include 221 - **nda_uri** : boolean (default True) - if True, existing shape and 222 ntv_type are not updated (but are created if not existing)''' 223 ndarray = Ndarray(ndarray) 224 if not self.nda is None: 225 return self.nda.update(ndarray, nda_uri=nda_uri) 226 self.nda = ndarray 227 return True 228 229 def to_json(self, **kwargs): 230 ''' convert a Xndarray into json-value. 231 232 *Parameters* 233 234 - **encoded** : Boolean (default False) - json-value if False else json-text 235 - **header** : Boolean (default True) - including xndarray type 236 - **noname** : Boolean (default False) - including data type and name if False 237 - **notype** : Boolean (default False) - including data type if False 238 - **novalue** : Boolean (default False) - including value if False 239 - **noshape** : Boolean (default True) - if True, without shape if dim < 1 240 - **format** : string (default 'full') - representation format of the ndarray, 241 - **extension** : string (default None) - type extension 242 ''' 243 option = {'notype': False, 'format': 'full', 244 'noshape': True, 'header': True, 'encoded': False, 245 'novalue': False, 'noname': False} | kwargs 246 if not option['format'] in ['full', 'complete']: 247 option['noshape'] = False 248 opt_nda = option | {'header': False} 249 nda_str = self.nda.to_json(**opt_nda) if not self.nda is None else None 250 lis = [nda_str, self.links, self.meta] 251 lis = [val for val in lis if not val is None] 252 return Nutil.json_ntv(None if option['noname'] else self.full_name, 253 None if option['noname'] else 'xndarray', 254 lis[0] if lis == [self.meta] else lis, 255 header=option['header'], encoded=option['encoded']) 256 257 def _to_json(self): 258 '''return dict of attributes''' 259 return {'name': self.name, 'ntv_type': self.ntv_type, 'uri': self.uri, 260 'nda': self.nda, 'meta': self.meta, 'links': self.links}
21class Xndarray: 22 ''' Representation of a labelled multidimensional Array 23 24 *Attributes :* 25 - **name** : string - name of the Xndarray 26 - **add_name** : string - additional name of the Xndarray 27 - **nda**: Ndarray - ndarray data 28 - **links**: list of string - links to other Xndarray 29 - **meta** : JsonValue - informations 30 31 *dynamic values (@property)* 32 - `darray` 33 - `ndarray` 34 - `uri` 35 - `shape` 36 - `ntv_type` 37 - `info` 38 - `mode` 39 - `xtype` 40 - `full_name` 41 - `json_name` 42 43 *methods* 44 - `to_json` 45 - `read_json (static method)` 46 - `set_ndarray` 47 ''' 48 49 def __init__(self, full_name, nda=None, links=None, 50 meta=None): 51 '''Xndarray constructor. 52 53 *Parameters* 54 55 - **full_name**: string (default None) - name with additional name 56 - **nda** : Ndarray (default None) - data 57 - **links**: List of string (default None) - dims or other names of associated Xndarray 58 - **ntv_type**: string (default None) - ntv_type to apply to data 59 - **meta**: dict (default None) - information 60 ''' 61 if isinstance(full_name, Xndarray): 62 self.name = full_name.name 63 self.add_name = full_name.add_name 64 self.nda = full_name.nda 65 self.links = full_name.links 66 self.meta = full_name.meta 67 return 68 self.name, self.add_name = Nutil.split_name(full_name) 69 self.nda = Ndarray(nda) if not nda is None else None 70 self.links = links if links else None 71 self.meta = meta if meta else None 72 if self.meta is None and self.nda is None: 73 raise NdarrayError('A Xndarray has to have metadata or Ndarray') 74 75 def __repr__(self): 76 '''return classname and number of value''' 77 return self.__class__.__name__ + '[' + self.full_name + ']' 78 79 def __str__(self): 80 '''return json string format''' 81 return json.dumps(self.to_json()) 82 83 def __eq__(self, other): 84 ''' equal if attributes are equal''' 85 if self.name != other.name or self.add_name != other.add_name: 86 return False 87 if self.links != other.links or self.meta != other.meta: 88 return False 89 if self.nda is None and other.nda is None: 90 return True 91 if self.nda is None or other.nda is None: 92 return False 93 return self.nda == other.nda 94 95 def __len__(self): 96 ''' len of ndarray''' 97 return len(self.nda) if self.nda is not None else 0 98 99 def __contains__(self, item): 100 ''' item of ndarray values''' 101 return item in self.nda if self.nda is not None else None 102 103 def __getitem__(self, ind): 104 ''' return ndarray value item''' 105 if self.nda is None: 106 return None 107 if isinstance(ind, tuple): 108 return [self.nda[i] for i in ind] 109 return self.nda[ind] 110 111 def __copy__(self): 112 ''' Copy all the data ''' 113 return self.__class__(self) 114 115 @property 116 def darray(self): 117 '''return the darray of the ndarray''' 118 return self.nda.darray if self.nda is not None else None 119 120 @property 121 def ndarray(self): 122 '''return the darray of the ndarray''' 123 return self.nda.ndarray if self.nda is not None else None 124 125 @property 126 def uri(self): 127 '''return the uri of the ndarray''' 128 return self.nda.uri if self.nda is not None else None 129 130 @property 131 def shape(self): 132 '''return the shape of the ndarray''' 133 return self.nda.shape if self.nda is not None else None 134 135 @property 136 def ntv_type(self): 137 '''return the ntv_type of the ndarray''' 138 return self.nda.ntv_type if self.nda is not None else None 139 140 @property 141 def mode(self): 142 '''return the mode of the ndarray''' 143 return self.nda.mode if self.nda is not None else 'undefined' 144 145 @property 146 def info(self): 147 ''' infos of the Xndarray''' 148 inf = {'name': self.full_name} 149 inf['length'] = len(self) 150 if self.nda: 151 inf['mode'] = self.mode 152 inf['ntvtype'] = self.ntv_type 153 inf['shape'] = self.shape 154 inf['uri'] = self.uri 155 inf['meta'] = self.meta 156 inf['xtype'] = self.xtype 157 inf['links'] = self.links 158 return {key: val for key, val in inf.items() if val} 159 160 @property 161 def xtype(self): 162 '''nature of the Xndarray (undefined, namedarray, variable, additional, 163 meta, inconsistent)''' 164 match [self.links, self.add_name, self.mode]: 165 case [_, _, 'inconsistent']: 166 return 'inconsistent' 167 case [_, _, 'undefined']: 168 return 'meta' 169 case [None, '', _]: 170 return 'namedarray' 171 case [_, '', _]: 172 return 'variable' 173 case [_, str(), _]: 174 return 'additional' 175 case _: 176 return 'inconsistent' 177 178 @property 179 def full_name(self): 180 '''concatenation of name and additional name''' 181 add_name = '.' + self.add_name if self.add_name else '' 182 return self.name + add_name 183 184 @property 185 def json_name(self): 186 '''concatenation of full_name and ntv_type''' 187 add_ntv_type = ':' + self.ntv_type if self.ntv_type else '' 188 return self.full_name + add_ntv_type 189 190 @staticmethod 191 def read_json(jsn, **kwargs): 192 ''' convert json data into a Xndarray. 193 194 *Parameters* 195 196 - **convert** : boolean (default True) - If True, convert json data with 197 non Numpy ntv_type into data with python type 198 ''' 199 option = {'convert': True} | kwargs 200 jso = json.loads(jsn) if isinstance(jsn, str) else jsn 201 value, full_name = Ntv.decode_json(jso)[:2] 202 203 meta = links = nda = None 204 match value: 205 case str(meta) | dict(meta): ... 206 case [list(nda)]: ... 207 case [list(nda), list(links)]: ... 208 case [list(nda), dict(meta)] | [list(nda), str(meta)]: ... 209 case [list(nda), list(links), dict(meta)]: ... 210 case [list(nda), list(links), str(meta)]: ... 211 case _: 212 return None 213 nda = Ndarray.read_json(nda, **option) if nda else None 214 return Xndarray(full_name, links=links, meta=meta, nda=nda) 215 216 def set_ndarray(self, ndarray, nda_uri=True): 217 '''set a new ndarray (nda) and return the result (True, False) 218 219 *Parameters* 220 221 - **ndarray** : string, list, np.ndarray, Ndarray - data to include 222 - **nda_uri** : boolean (default True) - if True, existing shape and 223 ntv_type are not updated (but are created if not existing)''' 224 ndarray = Ndarray(ndarray) 225 if not self.nda is None: 226 return self.nda.update(ndarray, nda_uri=nda_uri) 227 self.nda = ndarray 228 return True 229 230 def to_json(self, **kwargs): 231 ''' convert a Xndarray into json-value. 232 233 *Parameters* 234 235 - **encoded** : Boolean (default False) - json-value if False else json-text 236 - **header** : Boolean (default True) - including xndarray type 237 - **noname** : Boolean (default False) - including data type and name if False 238 - **notype** : Boolean (default False) - including data type if False 239 - **novalue** : Boolean (default False) - including value if False 240 - **noshape** : Boolean (default True) - if True, without shape if dim < 1 241 - **format** : string (default 'full') - representation format of the ndarray, 242 - **extension** : string (default None) - type extension 243 ''' 244 option = {'notype': False, 'format': 'full', 245 'noshape': True, 'header': True, 'encoded': False, 246 'novalue': False, 'noname': False} | kwargs 247 if not option['format'] in ['full', 'complete']: 248 option['noshape'] = False 249 opt_nda = option | {'header': False} 250 nda_str = self.nda.to_json(**opt_nda) if not self.nda is None else None 251 lis = [nda_str, self.links, self.meta] 252 lis = [val for val in lis if not val is None] 253 return Nutil.json_ntv(None if option['noname'] else self.full_name, 254 None if option['noname'] else 'xndarray', 255 lis[0] if lis == [self.meta] else lis, 256 header=option['header'], encoded=option['encoded']) 257 258 def _to_json(self): 259 '''return dict of attributes''' 260 return {'name': self.name, 'ntv_type': self.ntv_type, 'uri': self.uri, 261 'nda': self.nda, 'meta': self.meta, 'links': self.links}
Representation of a labelled multidimensional Array
Attributes :
- name : string - name of the Xndarray
- add_name : string - additional name of the Xndarray
- nda: Ndarray - ndarray data
- links: list of string - links to other Xndarray
- meta : JsonValue - informations
dynamic values (@property)
methods
to_json
read_json (static method)
set_ndarray
49 def __init__(self, full_name, nda=None, links=None, 50 meta=None): 51 '''Xndarray constructor. 52 53 *Parameters* 54 55 - **full_name**: string (default None) - name with additional name 56 - **nda** : Ndarray (default None) - data 57 - **links**: List of string (default None) - dims or other names of associated Xndarray 58 - **ntv_type**: string (default None) - ntv_type to apply to data 59 - **meta**: dict (default None) - information 60 ''' 61 if isinstance(full_name, Xndarray): 62 self.name = full_name.name 63 self.add_name = full_name.add_name 64 self.nda = full_name.nda 65 self.links = full_name.links 66 self.meta = full_name.meta 67 return 68 self.name, self.add_name = Nutil.split_name(full_name) 69 self.nda = Ndarray(nda) if not nda is None else None 70 self.links = links if links else None 71 self.meta = meta if meta else None 72 if self.meta is None and self.nda is None: 73 raise NdarrayError('A Xndarray has to have metadata or Ndarray')
Xndarray constructor.
Parameters
- full_name: string (default None) - name with additional name
- nda : Ndarray (default None) - data
- links: List of string (default None) - dims or other names of associated Xndarray
- ntv_type: string (default None) - ntv_type to apply to data
- meta: dict (default None) - information
115 @property 116 def darray(self): 117 '''return the darray of the ndarray''' 118 return self.nda.darray if self.nda is not None else None
return the darray of the ndarray
120 @property 121 def ndarray(self): 122 '''return the darray of the ndarray''' 123 return self.nda.ndarray if self.nda is not None else None
return the darray of the ndarray
125 @property 126 def uri(self): 127 '''return the uri of the ndarray''' 128 return self.nda.uri if self.nda is not None else None
return the uri of the ndarray
130 @property 131 def shape(self): 132 '''return the shape of the ndarray''' 133 return self.nda.shape if self.nda is not None else None
return the shape of the ndarray
135 @property 136 def ntv_type(self): 137 '''return the ntv_type of the ndarray''' 138 return self.nda.ntv_type if self.nda is not None else None
return the ntv_type of the ndarray
140 @property 141 def mode(self): 142 '''return the mode of the ndarray''' 143 return self.nda.mode if self.nda is not None else 'undefined'
return the mode of the ndarray
145 @property 146 def info(self): 147 ''' infos of the Xndarray''' 148 inf = {'name': self.full_name} 149 inf['length'] = len(self) 150 if self.nda: 151 inf['mode'] = self.mode 152 inf['ntvtype'] = self.ntv_type 153 inf['shape'] = self.shape 154 inf['uri'] = self.uri 155 inf['meta'] = self.meta 156 inf['xtype'] = self.xtype 157 inf['links'] = self.links 158 return {key: val for key, val in inf.items() if val}
infos of the Xndarray
160 @property 161 def xtype(self): 162 '''nature of the Xndarray (undefined, namedarray, variable, additional, 163 meta, inconsistent)''' 164 match [self.links, self.add_name, self.mode]: 165 case [_, _, 'inconsistent']: 166 return 'inconsistent' 167 case [_, _, 'undefined']: 168 return 'meta' 169 case [None, '', _]: 170 return 'namedarray' 171 case [_, '', _]: 172 return 'variable' 173 case [_, str(), _]: 174 return 'additional' 175 case _: 176 return 'inconsistent'
nature of the Xndarray (undefined, namedarray, variable, additional, meta, inconsistent)
178 @property 179 def full_name(self): 180 '''concatenation of name and additional name''' 181 add_name = '.' + self.add_name if self.add_name else '' 182 return self.name + add_name
concatenation of name and additional name
184 @property 185 def json_name(self): 186 '''concatenation of full_name and ntv_type''' 187 add_ntv_type = ':' + self.ntv_type if self.ntv_type else '' 188 return self.full_name + add_ntv_type
concatenation of full_name and ntv_type
190 @staticmethod 191 def read_json(jsn, **kwargs): 192 ''' convert json data into a Xndarray. 193 194 *Parameters* 195 196 - **convert** : boolean (default True) - If True, convert json data with 197 non Numpy ntv_type into data with python type 198 ''' 199 option = {'convert': True} | kwargs 200 jso = json.loads(jsn) if isinstance(jsn, str) else jsn 201 value, full_name = Ntv.decode_json(jso)[:2] 202 203 meta = links = nda = None 204 match value: 205 case str(meta) | dict(meta): ... 206 case [list(nda)]: ... 207 case [list(nda), list(links)]: ... 208 case [list(nda), dict(meta)] | [list(nda), str(meta)]: ... 209 case [list(nda), list(links), dict(meta)]: ... 210 case [list(nda), list(links), str(meta)]: ... 211 case _: 212 return None 213 nda = Ndarray.read_json(nda, **option) if nda else None 214 return Xndarray(full_name, links=links, meta=meta, nda=nda)
convert json data into a Xndarray.
Parameters
- convert : boolean (default True) - If True, convert json data with non Numpy ntv_type into data with python type
216 def set_ndarray(self, ndarray, nda_uri=True): 217 '''set a new ndarray (nda) and return the result (True, False) 218 219 *Parameters* 220 221 - **ndarray** : string, list, np.ndarray, Ndarray - data to include 222 - **nda_uri** : boolean (default True) - if True, existing shape and 223 ntv_type are not updated (but are created if not existing)''' 224 ndarray = Ndarray(ndarray) 225 if not self.nda is None: 226 return self.nda.update(ndarray, nda_uri=nda_uri) 227 self.nda = ndarray 228 return True
set a new ndarray (nda) and return the result (True, False)
Parameters
- ndarray : 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)
230 def to_json(self, **kwargs): 231 ''' convert a Xndarray into json-value. 232 233 *Parameters* 234 235 - **encoded** : Boolean (default False) - json-value if False else json-text 236 - **header** : Boolean (default True) - including xndarray type 237 - **noname** : Boolean (default False) - including data type and name if False 238 - **notype** : Boolean (default False) - including data type if False 239 - **novalue** : Boolean (default False) - including value if False 240 - **noshape** : Boolean (default True) - if True, without shape if dim < 1 241 - **format** : string (default 'full') - representation format of the ndarray, 242 - **extension** : string (default None) - type extension 243 ''' 244 option = {'notype': False, 'format': 'full', 245 'noshape': True, 'header': True, 'encoded': False, 246 'novalue': False, 'noname': False} | kwargs 247 if not option['format'] in ['full', 'complete']: 248 option['noshape'] = False 249 opt_nda = option | {'header': False} 250 nda_str = self.nda.to_json(**opt_nda) if not self.nda is None else None 251 lis = [nda_str, self.links, self.meta] 252 lis = [val for val in lis if not val is None] 253 return Nutil.json_ntv(None if option['noname'] else self.full_name, 254 None if option['noname'] else 'xndarray', 255 lis[0] if lis == [self.meta] else lis, 256 header=option['header'], encoded=option['encoded'])
convert a Xndarray into json-value.
Parameters
- encoded : Boolean (default False) - json-value if False else json-text
- header : Boolean (default True) - including xndarray type
- noname : Boolean (default False) - including data type and name if False
- notype : Boolean (default False) - 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 : string (default 'full') - representation format of the ndarray,
- extension : string (default None) - type extension