33written by: Hugo Oliveira ocehugo@gmail.com
44"""
55
6- # TODO write tests
76# TODO how we handle groups!?
87# TODO cleanup the user precedence rules of fill_values
98# TODO is_dim_consistent too complex
10- # TODO change_time too complex
119# TODO check_var too complex
1210# TODO createVariables too complex
13- # TODO implement from_file/from_cdl/from_json kwarg!?
1411# TODO Allow for attribute types to be specified in JSON
1512
1613import json
@@ -34,25 +31,23 @@ def __init__(self,
3431 variables is <key:[str,class,list,dict,int]> dict
3532 global_attributes is a <key:int> dict
3633
37- This class has __add__ to growth variables/dims/global attrs
38- and __sub__ to remove unwanted variables from
39- other :NetCDFGroupDict: instances.
34+ This class has __add__ to combine variables/dimensions/global attributes
35+ from :NetCDFGroupDict: instances.
4036
4137 Example:
4238 dmn = {'lon':360,'lat':210}
4339 var = {}
4440 var['water'] = {'type':'double','dimensions':['lat','lon']}
4541 w1 = NetCDFGroupDict(dimensions=dmn,variables=var)
42+
4643 dmn2 = {'time':300,'lon':720,'lat':330}
4744 var2 = {}
4845 var2['temp'] = {'type':'double','dimensions':['time','lat','lon']}
4946 w2 = NetCDFGroupDict(dimensions=dmn2,variables=var2)
47+
5048 w3 = w1+w2
5149 #w3.variables.keys() = ['water','temp']
5250 #w3.dimensions = {'time':300,'lon':360,'lat':210}
53- w4 = w2-w1
54- #w4.variables.keys() = ['temp']
55- #w4.dimensions = {'lon':720,'lat':330,'time':300}
5651 """
5752 self ._dimensions = None
5853 self ._variables = None
@@ -74,6 +69,7 @@ def __add__(self, other):
7469
7570 @property
7671 def dimensions (self ):
72+ """Property to store the dictionary mapping dimension names to their sizes."""
7773 return self ._dimensions
7874
7975 @dimensions .setter
@@ -83,6 +79,9 @@ def dimensions(self, value):
8379
8480 @property
8581 def variables (self ):
82+ """Property to store dictionary of variables. Keys are variable names, values are dictionaries of variable
83+ properties (dimensions, type, attributes, etc...)
84+ """
8685 return self ._variables
8786
8887 @variables .setter
@@ -92,6 +91,7 @@ def variables(self, value):
9291
9392 @property
9493 def global_attributes (self ):
94+ """Property to store dictionary of global attributes"""
9595 return self ._global_attributes
9696
9797 @global_attributes .setter
@@ -100,8 +100,7 @@ def global_attributes(self, value):
100100 self ._global_attributes = value
101101
102102 def is_dim_consistent (self ):
103- """Check if the variable dictionary
104- is consistent with current dimensions"""
103+ """Check if the variable dictionary is consistent with current dimensions"""
105104 checkdims = set ()
106105 for k in self .variables .keys ():
107106 try :
@@ -140,8 +139,7 @@ def is_dim_consistent(self):
140139
141140 @classmethod
142141 def check_var (cls , vardict , name = None ):
143- """ Check if the dictionary have all the required fields
144- to be defined as variable"""
142+ """Check if the dictionary have all the required fields to be defined as variable """
145143 if name is None :
146144 name = 'input'
147145
@@ -178,7 +176,7 @@ def check_var(cls, vardict, name=None):
178176
179177 @classmethod
180178 def check_consistency (self , dimdict , vdict ):
181- """ Check the dictionary """
179+ """Check that all dimensions referenced by variables in :vdict: are defined in the :dimdict: """
182180 alldims = dimdict .keys ()
183181 allvars = vdict .keys ()
184182 for k in allvars :
@@ -193,26 +191,25 @@ def check_consistency(self, dimdict, vdict):
193191
194192
195193class DatasetTemplate (NetCDFGroupDict ):
194+ """Template object used for creating netCDF files"""
195+
196196 def __init__ (self , * args , ** kwargs ):
197197 super (DatasetTemplate , self ).__init__ (* args , ** kwargs )
198- self .cattrs = set ([
199- 'zlib' , 'complevel' , 'shuffle' , 'fletcher32' , 'contiguous' ,
200- 'chunksizes' , 'endian' , 'least_significant_digit'
201- ])
202- self .fill_aliases = set (
203- ['fill_value' , 'missing_value' , 'FillValue' , '_FillValue' ])
198+ self .cattrs = {'zlib' , 'complevel' , 'shuffle' , 'fletcher32' , 'contiguous' , 'chunksizes' , 'endian' ,
199+ 'least_significant_digit' }
200+ self .fill_aliases = {'fill_value' , 'missing_value' , 'FillValue' , '_FillValue' }
204201 self .outfile = None
205202 self .ncobj = None
206203
207204 @classmethod
208205 def from_json (cls , path ):
209- # load the JSON file into a dict
206+ """Load template from a JSON file"""
207+
210208 with open (path ) as f :
211209 template = json .load (f , object_pairs_hook = OrderedDict )
212210
213- # e.g. this could call out to JSONschema to make sure the JSON has the expected
214- # high level structure, and could refuse to create the object right here if it wasn't correct
215211 # TODO: validate_template(template)
212+ # - just check that the only top-level properties are "dimensions", "variables" and "global_attribute"
216213
217214 return cls (dimensions = template .get ('dimensions' ),
218215 variables = template .get ('variables' ),
@@ -225,7 +222,8 @@ def _create_var_opts(self, vdict):
225222 `zlib`
226223 `least_significant_digit`
227224 `dimensions`
228- etc"""
225+ etc
226+ """
229227 vset = set (list (vdict .keys ()))
230228 inside = vset .intersection (self .cattrs )
231229 aliases = vset .intersection (self .fill_aliases )
@@ -303,7 +301,7 @@ def create_variables(self, **kwargs):
303301
304302 var_c_opts .update (cwargs )
305303
306- # user precendence
304+ # user precedence
307305 if ureq_fillvalue and vreq_fillvalue :
308306 [var_c_opts .pop (x ) for x in vreq_fillvalue ]
309307 fv_val = [var_c_opts .pop (x ) for x in ureq_fillvalue ]
0 commit comments