import sys
import unittest
import os
import tempfile
import numpy as np
from numpy import ma, seterr
from numpy.testing import assert_array_equal, assert_array_almost_equal
from netCDF4 import Dataset, default_fillvals

seterr(over='ignore') # don't print warning for overflow errors

# test automatic conversion of masked arrays, and
# packing/unpacking of short ints.

FILE_NAME1 = tempfile.NamedTemporaryFile(suffix='.nc', delete=False).name
FILE_NAME2 = tempfile.NamedTemporaryFile(suffix='.nc', delete=False).name
FILE_NAME3 = tempfile.NamedTemporaryFile(suffix='.nc', delete=False).name
datacheck1 =\
ma.array([0,5000.0,4000.0,0],dtype=np.float64,mask=[True,False,False,True])
datacheck2 =\
ma.array([3000.0,5000.0,4000.0,0],dtype=np.float64,mask=[False,False,False,True])
datacheck3 =\
ma.array([3000.0,5000.0,0,2000.0],dtype=np.float64,mask=[False,False,True,False])
mask = [False,True,False,False]
datacheck4 = ma.array([1.5625,0,3.75,4.125],mask=mask,dtype=np.float32)
fillval = default_fillvals[datacheck4.dtype.str[1:]]
datacheck5 = np.array([1.5625,fillval,3.75,4.125],dtype=np.float32)

class PrimitiveTypesTestCase(unittest.TestCase):

    def setUp(self):

        self.files = [FILE_NAME1]
        f = Dataset(FILE_NAME1,'w')
        x = f.createDimension('x',None)
        v = f.createVariable('v',np.int16,'x')
        v.scale_factor = np.array(1,np.float32)
        v.add_offset = np.array(32066,np.float32)
        v.missing_value = np.array(-9999,v.dtype)
        #v[0] not set, will be equal to _FillValue
        v[1]=5000
        v[2]=4000
        v[3]=v.missing_value
        f.close()

        self.files.append(FILE_NAME2)
        f = Dataset(FILE_NAME1,'r')
        # create a new file, copy data, but change missing value and
        # scale factor offset.
        f2 = Dataset(FILE_NAME2,'w')
        a = f2.createDimension('a',None)
        b = f2.createVariable('b',np.int16,'a')
        b.scale_factor = np.array(10.,np.float32)
        b.add_offset = np.array(0,np.float32)
        b.missing_value = np.array(9999,v.dtype)
        b[:] = f.variables['v'][:]
        f.close()
        f2.close()

        self.files.append(FILE_NAME3)
        f = Dataset(FILE_NAME3,'w')
        x = f.createDimension('x',None)
        # create variable with lossy compression
        v = f.createVariable('v',np.float32,'x',zlib=True,least_significant_digit=1)
        # assign masked array to that variable with one missing value.
        data =\
        ma.array([1.5678,99.99,3.75145,4.127654],mask=np.array([False,True,False,False],np.bool_))
        data.mask[1]=True
        v[:] = data
        f.close()

    def tearDown(self):
        # Remove the temporary files
        for f in self.files:
            os.remove(f)

    def runTest(self):
        """testing auto-conversion of masked arrays and packed integers"""

        f = Dataset(self.files[0])
        data = f.variables['v'][:]
        assert_array_almost_equal(data,datacheck1)
        f.close()

        f = Dataset(self.files[1])
        data = f.variables['b'][:]
        assert_array_almost_equal(data,datacheck1)
        f.close()

        f = Dataset(self.files[0],'a')
        # change first element from _FillValue to actual data.
        v = f.variables['v']
        v[0]=3000
        f.close()
        f = Dataset(self.files[0],'r')
        # read data back in, check.
        data = f.variables['v'][:]
        assert_array_almost_equal(data,datacheck2)
        f.close()

        f = Dataset(self.files[0],'a')
        # change 3rd element to missing, 4 element to valid data.
        v = f.variables['v']
        data = v[:]
        v[2]=-9999
        v[3]=2000
        f.close()
        f = Dataset(self.files[0],'r')
        # read data back in, check.
        data = f.variables['v'][:]
        assert_array_almost_equal(data,datacheck3)
        f.close()

        # check that masked arrays are handled correctly when lossy compression
        # is used.
        f = Dataset(self.files[2],'r')
        data = f.variables['v'][:]
        assert_array_almost_equal(data,datacheck4)
        assert_array_almost_equal(data.filled(),datacheck5)
        f.close()

if __name__ == '__main__':
    unittest.main()
