public static DenseMatrix ReadDenseMatrixFromFile(string fileName)
        {
            double[,] res = null;

            if (!ServiceTools.CheckIfDirectoryExists(fileName))
            {
                return(null);
            }
            NetCDFDataSet ds = null;

            try
            {
                ds = new NetCDFDataSet("msds:nc?file=" + fileName + "&enableRollback=false",
                                       ResourceOpenMode.ReadOnly);
            }
            catch (Exception ex)
            {
                throw ex;
            }

            //Variable<double> thDataVar = ds.AddVariable<double>("dataMatrix", dmData.ToArray(), "y", "x");
            //Variable<double> thDataVar = ds.Variables
            foreach (Variable theVar in ds)
            {
                res = (double[, ])theVar.GetData();
            }

            return(DenseMatrix.OfArray(res));
        }
        public static string DumpMatrixToNCFile(DenseMatrix dmData)
        {
            string baseDir          = Directory.GetCurrentDirectory() + "\\";
            string fileName         = DateTime.UtcNow.ToString("o").Replace(":", "-") + ".nc";
            string connectionString = "msds:nc?file=";

            connectionString += baseDir + fileName;

            NetCDFDataSet ds = null;

            try
            {
                ds = new NetCDFDataSet(connectionString, ResourceOpenMode.Create);
            }
            catch (Exception ex)
            {
                throw ex;
            }

            Variable <double> thDataVar = ds.AddVariable <double>("DataMatrix", dmData.ToArray(), "y", "x");

            try
            {
                ds.TryCommit();
            }
            catch (Exception exc)
            {
                return("failed-to-dump");
            }

            ds.Dispose();
            return(fileName);
        }
        protected NetCdfVariable(NetCDFDataSet dataSet, int varid, string name, string[] dims, bool assignID) :
            base(dataSet, name, dims, assignID)
        {
            this.initializing = true;
            this.varid        = varid;

            int res;

            // SByte can map to NC_BYTE or NC_CHAR
            if (typeof(DataType) == typeof(byte))
            {
                res = NetCDF.nc_inq_vartype(dataSet.NcId, varid, out var nativeType);
                NetCDFDataSet.HandleResult(res);
                isNcChar = NcType.NC_CHAR == nativeType;
            }
            UpdateDimIds();

            // Reading attributes
            int nattrs;

            res = NetCDF.nc_inq_varnatts(dataSet.NcId, varid, out nattrs);
            AttributeTypeMap atm = new AttributeTypeMap(dataSet.NcId, varid);

            NetCDFDataSet.HandleResult(res);
            for (int i = 0; i < nattrs; i++)
            {
                // Name
                string aname;
                res = NetCDF.nc_inq_attname(dataSet.NcId, varid, i, out aname);
                NetCDFDataSet.HandleResult(res);

                // Skip out internal attribute
                if (aname == AttributeTypeMap.AttributeName ||
                    aname == AttributeTypeMap.AttributeVarSpecialType)
                {
                    continue;
                }
                if (aname == AttributeTypeMap.AttributeVarActualShape)
                {
                    isPresentedAttrActualShape = true;
                    continue;
                }

                // Type
                object value = dataSet.ReadNetCdfAttribute(varid, aname, atm);
                if (aname == Metadata.KeyForMissingValue && typeof(DateTime) == typeof(DataType))
                {
                    if (value is string)
                    {
                        value = DateTime.Parse((string)value);
                    }
                }
                Metadata[aname] = value;
            }

            Initialize();
            initializing = false;
        }
Exemple #4
0
 private void GetNCInfo()
 {
     if (File.Exists(NCFileName))
     {
         NetCDFDataSet test = new NetCDFDataSet(NCFileName);
         _Variables = test.Variables;
         var buf = from vv in _Variables select vv.Name;
         NCVariables = buf.ToArray();
     }
 }
        ///<summary>
        /// Getting dimensions' ids from the NetCDF file.
        /// </summary>
        private void UpdateDimIds()
        {
            if (varid == NcConst.NC_GLOBAL)
            {
                this.dimids = new int[0];
                return;
            }
            int[] dimids = new int[Rank];
            int   res    = NetCDF.nc_inq_vardimid(NcId, varid, dimids);

            NetCDFDataSet.HandleResult(res);
            this.dimids = dimids;
        }
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        protected override int[] ReadShape()
        {
            if (initializing)
            {
                return(null);
            }

            int    res;
            IntPtr len;

            int[] shape = new int[dimids.Length];

            for (int i = 0; i < dimids.Length; i++)
            {
                res = NetCDF.nc_inq_dimlen(NcId, dimids[i], out len);
                NetCDFDataSet.HandleResult(res);

                shape[i] = (int)len;
            }

            if (isPresentedAttrActualShape)
            {
                // Actual shape of the variable is in the special attribute
                // for the NetCDF doesn't support variables like A[0,10]
                NetCDFDataSet nc = ((NetCDFDataSet)DataSet);

                NcType type;
                res = NetCDF.nc_inq_atttype(nc.NcId, varid, AttributeTypeMap.AttributeVarActualShape, out type);
                if (res == (int)ResultCode.NC_NOERR)
                {
                    if (type != NcType.NC_INT)
                    {
                        throw new NetCDFException("Reserved attribute " + AttributeTypeMap.AttributeVarActualShape + " has wrong type");
                    }

                    AttributeTypeMap atm = new AttributeTypeMap(nc.NcId, varid);
                    atm[AttributeTypeMap.AttributeVarActualShape] = typeof(int[]);
                    shape = (int[])nc.ReadNetCdfAttribute(varid, AttributeTypeMap.AttributeVarActualShape, atm);
                    if (shape.Length != Rank)
                    {
                        throw new NetCDFException("Value of reserved attribute " + AttributeTypeMap.AttributeVarActualShape + " has wrong length");
                    }
                }
                else if (res != (int)ResultCode.NC_ENOTATT)
                {
                    NetCDFDataSet.HandleResult(res);
                }
            }

            return(shape);
        }
        public static DenseMatrix ReadDenseMatrixFromFile(string fileName, string varName = "DataMatrix")
        {
            double[,] res = null;
            DenseMatrix dmRes = null;

            if (!ServiceTools.CheckIfDirectoryExists(fileName))
            {
                return(null);
            }

            NetCDFDataSet ds = null;

            try
            {
                ds = new NetCDFDataSet("msds:nc?file=" + fileName + "&enableRollback=false", ResourceOpenMode.ReadOnly);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            //Variable<double> thDataVar = ds.AddVariable<double>("dataMatrix", dmData.ToArray(), "y", "x");
            //Variable<double> thDataVar = ds.Variables
            foreach (Variable theVar in ds)
            {
                if (theVar.Name != varName)
                {
                    continue;
                }
                else
                {
                    if (theVar.TypeOfData == typeof(double))
                    {
                        res   = (double[, ])theVar.GetData();
                        dmRes = DenseMatrix.OfArray(res);
                    }
                    else if (theVar.TypeOfData == typeof(Single))
                    {
                        Single[,] res1 = (Single[, ])theVar.GetData();
                        dmRes          = DenseMatrix.Create(theVar.Dimensions[0].Length, theVar.Dimensions[1].Length, ((i, j) =>
                        {
                            return(Convert.ToDouble(res1[i, j]));
                        }));
                    }

                    break;
                }
            }

            return(dmRes);
        }
        public static void AddDataMatrixToFile(DenseMatrix dmData, string fileName, TextBox tbLog,
                                               bool absolutePath = false, string varName = "dataMatrix")
        {
            string baseDir          = "G:\\_gulevlab\\SkyIndexAnalyzerSolo_appData\\_dataDirectory\\";
            string connectionString = "msds:nc?file=";

            if (absolutePath)
            {
                if (!ServiceTools.CheckIfDirectoryExists(fileName))
                {
                    return;
                }
                connectionString += fileName;
            }
            else
            {
                if (!ServiceTools.CheckIfDirectoryExists(baseDir + fileName))
                {
                    return;
                }
                connectionString += baseDir + fileName;
            }

            NetCDFDataSet ds = null;

            try
            {
                ds = new NetCDFDataSet(connectionString, ResourceOpenMode.OpenOrCreate);
            }
            catch (Exception ex)
            {
                if (tbLog != null)
                {
                    ThreadSafeOperations.SetTextTB(tbLog, "Не получилось :( " + Environment.NewLine + ex.Message, true);
                }
                else
                {
                    throw ex;
                }
            }


            Variable <double> thDataVar;

            if (!ds.Variables.Contains(varName))
            {
                thDataVar = ds.AddVariable <double>(varName, dmData.ToArray(), "y", "x");
            }
            else
            {
                thDataVar = (Variable <double>)ds.Variables[varName];
                thDataVar.Append(dmData.ToArray());
            }


            try
            {
                ds.TryCommit();
            }
            catch (Exception ex)
            {
                if (tbLog != null)
                {
                    ThreadSafeOperations.SetTextTB(tbLog, "Не получилось :( " + Environment.NewLine + ex.Message, true);
                }
                else
                {
                    throw ex;
                }
            }

            ds.Dispose();
        }
        public override bool Execute(DotSpatial.Data.ICancelProgressHandler cancelProgressHandler)
        {
            //nc_out = new NetCDFDataSet("e:\\test.nc", Microsoft.Research.Science.Data.ResourceOpenMode.Create);
            //float[] xx = new float[10];
            //float[] yy = new float[10];
            //float[] dates = new float[2];
            //var var_name = "test";
            //var mat1 = new float[2, 10, 10];

            //nc_out.AddVariable(typeof(float), "longitude", xx, new string[] { "longitude", });
            //nc_out.AddVariable(typeof(float), "latitude", yy, new string[] { "latitude" });
            //var dt = nc_out.AddVariable(typeof(float), "time", dates, new string[] { "time" });
            //var test = nc_out.AddVariable(typeof(float), var_name, mat1, new string[] { "time", "latitude", "longitude" });
            //nc_out.Commit();
            //var newmat = new float[1, 10, 10];

            //dt.Append(new float[1]);
            //test.Append(newmat);
            //nc_out.Commit();
            //    return true;

            var var_index = 0;
            var mat       = Get3DMat(Source, ref var_index);
            int progress  = 0;
            int nsteps    = mat.Size[1];

            var grid   = ProjectService.Project.Model.Grid as RegularGrid;
            var lonlat = grid.GetLonLatAxis();

            var times = new float[nsteps];

            if (mat.DateTimes != null)
            {
                for (int t = 0; t < nsteps; t++)
                {
                    times[t] = mat.DateTimes[t].ToFileTime();
                }
            }
            else
            {
                for (int t = 0; t < nsteps; t++)
                {
                    times[t] = DateTime.Now.AddDays(t).ToFileTime();
                }
            }
            var mat_step = grid.To3DMatrix <float>(mat[var_index, "0", ":"], 0);

            nc_out = new NetCDFDataSet("e:\\test.nc");
            //   nc_out = new NetCDFDataSet(OutputFileName);
            nc_out.AddVariable(typeof(float), "longitude", lonlat[0], new string[] { "longitude", });
            nc_out.AddVariable(typeof(float), "latitude", lonlat[1], new string[] { "latitude" });
            var nc_dt  = nc_out.AddVariable(typeof(float), "time", new float[] { times[0] }, new string[] { "time" });
            var nc_var = nc_out.AddVariable(typeof(float), VariableName, mat_step, new string[] { "time", "latitude", "longitude" });

            nc_out.Commit();
            for (int t = 1; t < nsteps; t++)
            {
                mat_step = grid.To3DMatrix <float>(mat[var_index, "0", ":"], t);
                nc_var.Append(mat_step);
                nc_dt.Append(new float[] { times[t] });
                nc_out.Commit();

                progress = t * 100 / nsteps;
                cancelProgressHandler.Progress("Package_Tool", progress, "Processing step:" + t);
            }
            return(true);
        }
        public static void AddVariousDataToFile(Dictionary <string, object> dataToWrite, string fileName)
        {
            if (!ServiceTools.CheckIfDirectoryExists(fileName))
            {
                return;
            }

            string connectionString = "msds:nc?file=";

            connectionString += fileName;
            NetCDFDataSet ds = null;

            try
            {
                ds = new NetCDFDataSet(connectionString, ResourceOpenMode.OpenOrCreate);
            }
            catch (Exception ex)
            {
                throw ex;
            }

            foreach (KeyValuePair <string, object> keyValuePair in dataToWrite)
            {
                if (keyValuePair.Value.GetType() == typeof(DenseMatrix))
                {
                    if (ds.Variables.Contains(keyValuePair.Key))
                    {
                        Variable <double> theDataVar = (Variable <double>)ds.Variables[keyValuePair.Key];
                        theDataVar.Append(((DenseMatrix)keyValuePair.Value).ToArray());
                    }
                    else
                    {
                        Variable <double> theDataVar = ds.AddVariable <double>(keyValuePair.Key,
                                                                               ((DenseMatrix)(keyValuePair.Value)).ToArray(), "y", "x");
                    }
                }

                if (keyValuePair.Value.GetType() == typeof(DenseVector))
                {
                    if (ds.Variables.Contains(keyValuePair.Key))
                    {
                        Variable <double> theDataVar = (Variable <double>)ds.Variables[keyValuePair.Key];
                        theDataVar.Append(((DenseVector)keyValuePair.Value).ToArray());
                    }
                    else
                    {
                        Variable <double> theDataVar = ds.AddVariable <double>(keyValuePair.Key,
                                                                               ((DenseVector)(keyValuePair.Value)).ToArray(), keyValuePair.Key);
                    }
                }

                if (keyValuePair.Value.GetType() == typeof(long[]))
                {
                    if (ds.Variables.Contains(keyValuePair.Key))
                    {
                        Variable <long> theDataVar = (Variable <long>)ds.Variables[keyValuePair.Key];
                        theDataVar.Append((long[])(keyValuePair.Value));
                    }
                    else
                    {
                        Variable <long> theDataVar = ds.AddVariable <long>(keyValuePair.Key, (long[])(keyValuePair.Value),
                                                                           keyValuePair.Key);
                    }
                }

                if (keyValuePair.Value.GetType() == typeof(int[]))
                {
                    if (ds.Variables.Contains(keyValuePair.Key))
                    {
                        Variable <int> theDataVar = (Variable <int>)ds.Variables[keyValuePair.Key];
                        theDataVar.Append((int[])(keyValuePair.Value));
                    }
                    else
                    {
                        Variable <int> theDataVar = ds.AddVariable <int>(keyValuePair.Key, (int[])(keyValuePair.Value),
                                                                         keyValuePair.Key);
                    }
                }

                if (keyValuePair.Value.GetType() == typeof(string[]))
                {
                    if (ds.Variables.Contains(keyValuePair.Key))
                    {
                        Variable <string> theDataVar = (Variable <string>)ds.Variables[keyValuePair.Key];
                        theDataVar.Append((string[])(keyValuePair.Value));
                    }
                    else
                    {
                        Variable <string> theDataVar = ds.AddVariable <string>(keyValuePair.Key, (string[])(keyValuePair.Value),
                                                                               keyValuePair.Key);
                    }
                }
            }

            try
            {
                ds.TryCommit();
            }
            catch (Exception ex)
            {
                throw ex;
            }

            ds.Dispose();
        }
        public static void SaveVariousDataToFile(Dictionary <string, object> dataToWrite, string fileName)
        {
            if (!ServiceTools.CheckIfDirectoryExists(fileName))
            {
                return;
            }

            string connectionString = "msds:nc?file=";

            connectionString += fileName;
            // connectionString += "&deflate=best";
            NetCDFDataSet ds = null;

            try
            {
                ds = new NetCDFDataSet(connectionString, ResourceOpenMode.Create);
            }
            catch (Exception ex)
            {
                throw ex;
            }

            foreach (KeyValuePair <string, object> keyValuePair in dataToWrite)
            {
                if (keyValuePair.Value.GetType() == typeof(DenseMatrix))
                {
                    try
                    {
                        Variable <double> theDataVar = ds.AddVariable <double>(keyValuePair.Key, ((DenseMatrix)(keyValuePair.Value)).ToArray(), "y", "x");
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }

                if (keyValuePair.Value.GetType() == typeof(DenseVector))
                {
                    try
                    {
                        Variable <double> theDataVar = ds.AddVariable <double>(keyValuePair.Key, ((DenseVector)(keyValuePair.Value)).ToArray(), keyValuePair.Key);
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }

                if (keyValuePair.Value.GetType() == typeof(long[]))
                {
                    try
                    {
                        Variable <long> theDataVar = ds.AddVariable <long>(keyValuePair.Key, (long[])(keyValuePair.Value), keyValuePair.Key);
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }


                if (keyValuePair.Value.GetType() == typeof(long[, ]))
                {
                    try
                    {
                        Variable <long> theDataVar = ds.AddVariable <long>(keyValuePair.Key, (long[, ])(keyValuePair.Value), "y", "x");
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }


                if (keyValuePair.Value.GetType() == typeof(int[]))
                {
                    try
                    {
                        Variable <int> theDataVar = ds.AddVariable <int>(keyValuePair.Key, (int[])(keyValuePair.Value), keyValuePair.Key);
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }


                if (keyValuePair.Value.GetType() == typeof(int[, ]))
                {
                    try
                    {
                        Variable <int> theDataVar = ds.AddVariable <int>(keyValuePair.Key, (int[, ])(keyValuePair.Value), "y", "x");
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }


                if (keyValuePair.Value.GetType() == typeof(short[]))
                {
                    try
                    {
                        Variable <short> theDataVar = ds.AddVariable <short>(keyValuePair.Key, (short[])(keyValuePair.Value), keyValuePair.Key);
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }


                if (keyValuePair.Value.GetType() == typeof(short[, ]))
                {
                    try
                    {
                        Variable <short> theDataVar = ds.AddVariable <short>(keyValuePair.Key, (short[, ])(keyValuePair.Value), "y", "x");
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }



                if (keyValuePair.Value.GetType() == typeof(byte[]))
                {
                    try
                    {
                        Variable <byte> theDataVar = ds.AddVariable <byte>(keyValuePair.Key, (byte[])(keyValuePair.Value), keyValuePair.Key);
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }


                if (keyValuePair.Value.GetType() == typeof(byte[, ]))
                {
                    try
                    {
                        Variable <byte> theDataVar = ds.AddVariable <byte>(keyValuePair.Key, (byte[, ])(keyValuePair.Value), "y", "x");
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }



                if (keyValuePair.Value.GetType() == typeof(byte[, , ]))
                {
                    try
                    {
                        Variable <byte> theDataVar = ds.AddVariable <byte>(keyValuePair.Key, (byte[, , ])(keyValuePair.Value), "y", "x", "z");
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }



                if (keyValuePair.Value.GetType() == typeof(string[]))
                {
                    Variable <string> theDataVar = ds.AddVariable <string>(keyValuePair.Key, (string[])(keyValuePair.Value), keyValuePair.Key);
                }
            }



            try
            {
                ds.TryCommit();
            }
            catch (Exception ex)
            {
                throw ex;
            }

            ds.Dispose();
        }
        public static Dictionary <string, object> ReadDataFromFile(string fileName, List <string> varNames = null)
        {
            if (!ServiceTools.CheckIfDirectoryExists(fileName))
            {
                return(null);
            }

            Dictionary <string, object> retDict = new Dictionary <string, object>();

            double[,] res = null;
            NetCDFDataSet ds = null;

            try
            {
                ds = new NetCDFDataSet("msds:nc?file=" + fileName + "&enableRollback=false", ResourceOpenMode.ReadOnly);
            }
            catch (Exception ex)
            {
                throw ex;
            }

            foreach (Variable theVar in ds)
            {
                bool loadThisVar = false;
                if (varNames == null)
                {
                    loadThisVar = true;
                }
                else if (varNames.Contains(theVar.Name))
                {
                    loadThisVar = true;
                }
                if (!loadThisVar)
                {
                    continue;
                }

                if (theVar.TypeOfData == typeof(double))
                {
                    if (theVar.Dimensions.Count == 1)
                    {
                        double[] res1 = (double[])theVar.GetData();
                        retDict.Add(theVar.Name, DenseVector.OfEnumerable(res1));
                    }
                    else if (theVar.Dimensions.Count == 2)
                    {
                        double[,] res1 = (double[, ])theVar.GetData();
                        retDict.Add(theVar.Name, DenseMatrix.OfArray(res1));
                    }
                }



                if (theVar.TypeOfData == typeof(Single))
                {
                    if (theVar.Dimensions.Count == 1)
                    {
                        Single[]    res1   = (Single[])theVar.GetData();
                        DenseVector dvRes1 = DenseVector.Create(theVar.Dimensions[0].Length,
                                                                i => Convert.ToDouble(res1[i]));
                        retDict.Add(theVar.Name, dvRes1);
                    }
                    else if (theVar.Dimensions.Count == 2)
                    {
                        Single[,] res1 = (Single[, ])theVar.GetData();
                        DenseMatrix dmRes = DenseMatrix.Create(theVar.Dimensions[0].Length, theVar.Dimensions[1].Length,
                                                               ((i, j) =>
                        {
                            return(Convert.ToDouble(res1[i, j]));
                        }));
                        retDict.Add(theVar.Name, dmRes);
                    }
                }



                if (theVar.TypeOfData == typeof(long))
                {
                    if (theVar.Dimensions.Count == 1)
                    {
                        long[] res1 = (long[])theVar.GetData();
                        retDict.Add(theVar.Name, res1);
                    }
                    else if (theVar.Dimensions.Count == 2)
                    {
                        long[,] res1 = (long[, ])theVar.GetData();
                        retDict.Add(theVar.Name, res1);
                    }
                }


                if (theVar.TypeOfData == typeof(int))
                {
                    if (theVar.Dimensions.Count == 1)
                    {
                        int[] res1 = (int[])theVar.GetData();
                        retDict.Add(theVar.Name, res1);
                    }
                    else if (theVar.Dimensions.Count == 2)
                    {
                        int[,] res1 = (int[, ])theVar.GetData();
                        retDict.Add(theVar.Name, res1);
                    }
                }


                if (theVar.TypeOfData == typeof(string))
                {
                    string[] res1 = (string[])theVar.GetData();
                    retDict.Add(theVar.Name, res1);
                }
            }

            return(retDict);
        }
        protected override Array ReadData(int[] origin, int[] stride, int[] shape)
        {
            // TODO: there is a problem using nc_get_vars_string!!!
            // nc_get_vars_string still doesn't work in NetCDF4.1.3 "Mapped access for atomic types only."
            // remove this trick:
            if (TypeOfData == typeof(string))
            {
                return(base.ReadData(origin, stride, shape));
            }

            if (origin == null)
            {
                origin = new int[Rank];
            }

            if (shape == null)
            {
                shape = ReadShape();
                for (int i = 0; i < shape.Length; i++)
                {
                    shape[i] -= origin[i];
                }
            }
            if (stride == null)
            {
                origin = new int[Rank];
                for (int i = 0; i < Rank; i++)
                {
                    stride[i] = 1;
                }
            }
            if (Rank == 0)
            {
                shape = new int[] { 1 }
            }
            ;                            // the place for data

            // Total number of elements in the array
            int n = 1;

            for (int i = 0; i < shape.Length; i++)
            {
                n *= shape[i];
            }

            int res;

            switch (Type.GetTypeCode(TypeOfData))
            {
            case TypeCode.Boolean:
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(bool), Rank == 0 ? new int[1] : new int[Rank]));
                }
                byte[] blData = new byte[n];
                res = NetCDF.nc_get_vars_ubyte(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), blData);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArrayBool(blData, shape));

            case TypeCode.DateTime:
                double[] dtData = new double[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(DateTime), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_double(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), dtData);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArrayDateTime(dtData, shape));

            case TypeCode.Double:
                double[] data = new double[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(double), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_double(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), data);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(data, shape));

            case TypeCode.Single:
                float[] fdata = new float[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(float), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_float(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), fdata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(fdata, shape));

            case TypeCode.Int64:
                long[] ldata = new long[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(long), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_longlong(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), ldata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(ldata, shape));

            case TypeCode.UInt64:
                ulong[] uldata = new ulong[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(ulong), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_ulonglong(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), uldata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(uldata, shape));


            case TypeCode.Int32:
                int[] idata = new int[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(int), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_int(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), idata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(idata, shape));

            case TypeCode.UInt32:
                uint[] uidata = new uint[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(uint), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_uint(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), uidata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(uidata, shape));

            case TypeCode.Int16:
                short[] sdata = new short[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(short), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_short(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), sdata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(sdata, shape));

            case TypeCode.UInt16:
                ushort[] usdata = new ushort[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(ushort), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_ushort(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), usdata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(usdata, shape));


            case TypeCode.Byte:
                byte[] bdata = new byte[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(byte), Rank == 0 ? new int[1] : new int[Rank]));
                }
                if (isNcChar)
                {
                    res = NetCDF.nc_get_vars_text(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), bdata);
                }
                else
                {
                    res = NetCDF.nc_get_vars_ubyte(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), bdata);
                }
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(bdata, shape));

            case TypeCode.SByte:
                SByte[] cdata = new SByte[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(SByte), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_schar(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), cdata);
                //if (res == -56)
                //    res = NetCDF.nc_get_vars_text(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), cdata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(cdata, shape));

            case TypeCode.String:
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(string), Rank == 0 ? new int[1] : new int[Rank]));
                }
                string[] strings = new string[n];
                res = NetCDF.nc_get_vars_string(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), strings);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArrayString(strings, shape));

            default:
                throw new NotSupportedException("Unsupported type of data.");
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="origin"></param>
        /// <param name="a"></param>
        protected override void WriteData(int[] origin, Array a)
        {
            if (origin == null)
            {
                origin = new int[Rank];
            }

            int[] shape = new int[origin.Length];
            for (int i = 0; i < shape.Length; i++)
            {
                shape[i] = a.GetLength(i);
            }

            int res;

            switch (Type.GetTypeCode(TypeOfData))
            {
            case TypeCode.Boolean:
                byte[] bldata = FromMultidimArrayBool(a);
                res = NetCDF.nc_put_vara_ubyte(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), bldata);
                NetCDFDataSet.HandleResult(res);
                return;

            case TypeCode.DateTime:
                double[] dtData = FromMultidimArrayDateTime(a);
                res = NetCDF.nc_put_vara_double(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), dtData);
                NetCDFDataSet.HandleResult(res);
                return;

            case TypeCode.Double:
                double[] data = FromMultidimArray <double>(a);
                res = NetCDF.nc_put_vara_double(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), data);
                NetCDFDataSet.HandleResult(res);
                return;

            case TypeCode.Single:
                float[] fdata = FromMultidimArray <float>(a);
                res = NetCDF.nc_put_vara_float(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), fdata);
                NetCDFDataSet.HandleResult(res);
                return;

            case TypeCode.Int64:
                long[] ldata = FromMultidimArray <long>(a);
                res = NetCDF.nc_put_vara_longlong(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ldata);
                NetCDFDataSet.HandleResult(res);
                return;

            case TypeCode.UInt64:
                ulong[] uldata = FromMultidimArray <ulong>(a);
                res = NetCDF.nc_put_vara_ulonglong(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), uldata);
                NetCDFDataSet.HandleResult(res);
                return;

            case TypeCode.Int32:
                int[] idata = FromMultidimArray <int>(a);
                res = NetCDF.nc_put_vara_int(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), idata);
                NetCDFDataSet.HandleResult(res);
                return;

            case TypeCode.UInt32:
                uint[] uidata = FromMultidimArray <uint>(a);
                res = NetCDF.nc_put_vara_uint(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), uidata);
                NetCDFDataSet.HandleResult(res);
                return;

            case TypeCode.Int16:
                short[] sdata = FromMultidimArray <short>(a);
                res = NetCDF.nc_put_vara_short(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), sdata);
                NetCDFDataSet.HandleResult(res);
                return;

            case TypeCode.UInt16:
                ushort[] usdata = FromMultidimArray <ushort>(a);
                res = NetCDF.nc_put_vara_ushort(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), usdata);
                NetCDFDataSet.HandleResult(res);
                return;

            case TypeCode.Byte:
                byte[] bdata = FromMultidimArray <byte>(a);
                if (isNcChar)
                {
                    res = NetCDF.nc_put_vara_text(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), bdata);
                }
                else
                {
                    res = NetCDF.nc_put_vara_ubyte(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), bdata);
                }
                NetCDFDataSet.HandleResult(res);
                return;

            case TypeCode.SByte:
                sbyte[] sbdata = FromMultidimArray <sbyte>(a);
                res = NetCDF.nc_put_vara_schar(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), sbdata);
                NetCDFDataSet.HandleResult(res);
                return;

            case TypeCode.String:
                string[] strdata = FromMultidimArrayString(a);
                res = NetCDF.nc_put_vara_string(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), strdata);
                NetCDFDataSet.HandleResult(res);
                return;

            default:
                throw new NotSupportedException("Unsupported type of data.");
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="origin"></param>
        /// <param name="shape"></param>
        /// <returns></returns>
        protected override Array ReadData(int[] origin, int[] shape)
        {
            if (origin == null)
            {
                origin = new int[Rank];
            }

            if (shape == null)
            {
                shape = ReadShape();
                for (int i = 0; i < shape.Length; i++)
                {
                    shape[i] -= origin[i];
                }
            }
            if (Rank == 0)
            {
                shape = new int[] { 1 }
            }
            ;                                            // the place for data

            // Total number of elements in the array
            int n = 1;

            for (int i = 0; i < shape.Length; i++)
            {
                n *= shape[i];
            }

            int res;

            switch (Type.GetTypeCode(TypeOfData))
            {
            case TypeCode.Boolean:
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(bool), Rank == 0 ? new int[1] : new int[Rank]));
                }
                byte[] blData = new byte[n];
                res = NetCDF.nc_get_vara_ubyte(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), blData);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArrayBool(blData, shape));

            case TypeCode.DateTime:
                double[] dtData = new double[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(DateTime), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vara_double(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), dtData);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArrayDateTime(dtData, shape));

            case TypeCode.Double:
                double[] data = new double[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(double), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vara_double(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), data);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(data, shape));

            case TypeCode.Single:
                float[] fdata = new float[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(float), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vara_float(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), fdata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(fdata, shape));

            case TypeCode.Int64:
                long[] ldata = new long[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(long), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vara_longlong(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ldata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(ldata, shape));

            case TypeCode.UInt64:
                ulong[] uldata = new ulong[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(ulong), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vara_ulonglong(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), uldata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(uldata, shape));


            case TypeCode.Int32:
                int[] idata = new int[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(int), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vara_int(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), idata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(idata, shape));

            case TypeCode.UInt32:
                uint[] uidata = new uint[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(uint), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vara_uint(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), uidata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(uidata, shape));

            case TypeCode.Int16:
                short[] sdata = new short[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(short), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vara_short(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), sdata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(sdata, shape));

            case TypeCode.UInt16:
                ushort[] usdata = new ushort[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(ushort), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vara_ushort(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), usdata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(usdata, shape));


            case TypeCode.Byte:
                byte[] bdata = new byte[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(byte), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vara_ubyte(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), bdata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(bdata, shape));

            case TypeCode.SByte:
                SByte[] cdata = new SByte[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(SByte), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vara_schar(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), cdata);
                if (res == -56)
                {
                    res = NetCDF.nc_get_vara_text(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), cdata);
                }
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(cdata, shape));

            case TypeCode.String:
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(string), Rank == 0 ? new int[1] : new int[Rank]));
                }
                IntPtr[] strdata = new IntPtr[n];
                res = NetCDF.nc_get_vara_string(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), strdata);
                NetCDFDataSet.HandleResult(res);

                string[] strings = new string[n];
                for (int i = 0; i < n; i++)
                {
                    strings[i] = UTF8Marshal.PtrToStringUTF8(strdata[i]);                            //Marshal.PtrToStringAnsi(strdata[i]);
                    res        = NetCDF.nc_free_string(new IntPtr(1), new IntPtr[] { strdata[i] });
                    NetCDFDataSet.HandleResult(res);
                }

                // TODO: the memory must be freed?
                //res = NetCDF.nc_free_string(1, strdata);
                //NetCDFDataSet.HandleResult(res);

                return(ToMultidimArray(strings, shape));

            default:
                throw new NotSupportedException("Unsupported type of data.");
            }
        }
 public NetCDFGlobalMetadataVariable(NetCDFDataSet ds)
     : base(ds, NetCDF.NC_GLOBAL, String.Empty, new string[0], false)
 {
     this.ID = NetCDFDataSet.GlobalMetadataVariableID;
 }
        /// <summary>
        ///
        /// </summary>
        /// <param name="proposedChanges"></param>
        internal protected override void OnPrecommit(Variable.Changes proposedChanges)
        {
            NetCDF.nc_enddef(NcId);
            base.OnPrecommit(proposedChanges);
            if (((NetCDFDataSet)DataSet).Initializing)
            {
                return;
            }
            NetCDF.nc_redef(NcId);

            NetCDFDataSet    dataSet = (NetCDFDataSet)this.DataSet;
            AttributeTypeMap atm     = new AttributeTypeMap(dataSet.NcId, varid);

            /* Updating attributes in the netCDF file */
            foreach (var item in proposedChanges.MetadataChanges)
            {
                dataSet.WriteNetCdfAttribute(varid, item.Key, item.Value, atm);
            }

            // NetCDF doesn't supports storing of arrays of kind A[x:0, y:10]
            // so we keep this actual shape in the reserved attribute.
            if (Rank > 1)
            {
                int min, max;
                GetMinMax(proposedChanges.Shape, out min, out max);
                if (min == 0 && max > 0)
                {
                    dataSet.WriteNetCdfAttribute(varid, AttributeTypeMap.AttributeVarActualShape,
                                                 proposedChanges.Shape, atm);
                    isPresentedAttrActualShape = true;
                }
                else if (isPresentedAttrActualShape)
                {
                    NetCDF.nc_del_att(NcId, varid, AttributeTypeMap.AttributeVarActualShape);
                    isPresentedAttrActualShape = false;
                }
            }

            atm.Store();

            /* Saving attached coordinate systems as "coordinates" attributes.
             * Common netCDF model supports for only one such attribute,
             * so all others CS except first are not compatible with that model.
             * Their attribute names are "coordinates2","coordinates3" etc.
             * Names of coordinate systems are provided with corresponed
             * attributes "coordinatesName","coordinates2Name",...
             */
            if (proposedChanges.CoordinateSystems != null)
            {
                int n = proposedChanges.InitialSchema.CoordinateSystems.Length;

                foreach (var cs in proposedChanges.CoordinateSystems)
                {
                    if (Array.Exists(proposedChanges.InitialSchema.CoordinateSystems, css => css == cs.Name))
                    {
                        continue;
                    }

                    // This CS has been added.
                    string name = "coordinates";
                    if (n > 0)
                    {
                        name += n.ToString();
                    }
                    n++;

                    StringBuilder sb    = new StringBuilder();
                    bool          first = true;
                    foreach (Variable axis in cs.Axes)
                    {
                        if (!first)
                        {
                            sb.Append(' ');
                        }
                        else
                        {
                            first = false;
                        }
                        sb.Append(axis.Name);
                    }
                    dataSet.WriteNetCdfAttribute(varid, name, sb.ToString(), null);
                    dataSet.WriteNetCdfAttribute(varid, name + "Name", cs.Name, null);
                }
            }
        }
        internal static NetCdfVariable <DataType> Create(NetCDFDataSet dataSet, string name, string[] dims)
        {
            if (dims == null) // scalar variable
            {
                dims = new string[0];
            }

            int res;

            /* Getting exsting dims and creating new */
            int[] dimids = new int[dims.Length];
            for (int i = 0; i < dims.Length; i++)
            {
                int id;
                res = NetCDF.nc_inq_dimid(dataSet.NcId, dims[i], out id);
                if (res == (int)ResultCode.NC_NOERR)
                {
                    dimids[i] = id;
                }
                else if (res == (int)ResultCode.NC_EBADDIM)
                {
                    // Creating new dimension
                    res = NetCDF.nc_def_dim(dataSet.NcId, dims[i], new IntPtr(NcConst.NC_UNLIMITED), out id);
                    NetCDFDataSet.HandleResult(res);
                    dimids[i] = id;
                }
                else
                {
                    NetCDFDataSet.HandleResult(res);
                }
            }

            /* Creating variable */
            int varid;

            string nc_name = GetNetCDFName(name);

            if (nc_name != name)
            {
                Debug.WriteLineIf(NetCDFDataSet.TraceNetCDFDataSet.TraceVerbose, "NetCDF: name has illegal chars; internal variable name is " + nc_name);
            }

            res = NetCDF.nc_def_var(dataSet.NcId, nc_name, NetCDF.GetNcType(typeof(DataType)), dimids, out varid);
            for (int count = 1; res == (int)ResultCode.NC_ENAMEINUSE;)
            {
                // Keep trying to create variable with different names
                res = NetCDF.nc_def_var(dataSet.NcId, String.Format("{0}_{1}", nc_name, count++), NetCDF.GetNcType(typeof(DataType)), dimids, out varid);
            }
            NetCDFDataSet.HandleResult(res);

            // Non scalar variables can be compressed.
            // It is regulated by the uri parameter "deflate".
            if (dims.Length > 0)
            {
                if (dataSet.Deflate == DeflateLevel.Off)
                {
                    res = NetCDF.nc_def_var_deflate(dataSet.NcId, varid, 0, 0, 0);
                }
                else
                {
                    res = NetCDF.nc_def_var_deflate(dataSet.NcId, varid, 0, 1, (int)dataSet.Deflate);
                }
                NetCDFDataSet.HandleResult(res);
            }

            if (dims.Length > 0) // non-scalar variable
            {
                IntPtr[] chunksizes = null;
                if (dataSet.ChunkSizes != null && dataSet.ChunkSizes.Length == dims.Length)
                {
                    if (dataSet.ChunkSizes.All(sz => sz >= 1))
                    {
                        chunksizes = dataSet.ChunkSizes.Select(sz => new IntPtr(sz)).ToArray();
                    }
                    else
                    {
                        throw new NotSupportedException("Chunk size cannot be less than 1");
                    }
                }

                if (chunksizes == null) // then use default chunk sizes
                {
                    chunksizes = new IntPtr[dims.Length];
                    int chunk = ChunkSizeSelector.GetChunkSize(typeof(DataType), dims.Length);

#if DEBUG
                    if (NetCDFDataSet.TraceNetCDFDataSet.TraceInfo)
                    {
                        StringBuilder sbChunk = new StringBuilder();
                        sbChunk.Append("NetCDF: Chunk sizes for rank ").Append(dims.Length).Append(": ");
                        for (int i = 0; i < dims.Length; i++)
                        {
                            sbChunk.Append(chunk).Append(",");
                        }
                        Debug.WriteLineIf(NetCDFDataSet.TraceNetCDFDataSet.TraceInfo, sbChunk.ToString());
                    }
#endif

                    for (int i = 0; i < dims.Length; i++)
                    {
                        chunksizes[i] = new IntPtr(chunk);
                    }
                }

                res = NetCDF.nc_def_var_chunking(dataSet.NcId, varid, 0, chunksizes);
                NetCDFDataSet.HandleResult(res);
            }

            if (typeof(DataType) == typeof(DateTime))
            {
                NetCDFDataSet.NcPutAttText(dataSet.NcId, varid, "Units", NetCDFDataSet.dateTimeUnits);
            }
            else if (typeof(DataType) == typeof(bool))
            {
                NetCDFDataSet.NcPutAttText(dataSet.NcId, varid, AttributeTypeMap.AttributeVarSpecialType, typeof(bool).ToString());
            }

            return(new NetCdfVariable <DataType>(dataSet, varid, name, dims));
        }
        internal static NetCdfVariable <DataType> Read(NetCDFDataSet dataSet, int varid)
        {
            string name;
            NcType ncType;

            int[] dimIds;
            int   natts, res, ndims;

            // Number of dimensions
            res = NetCDF.nc_inq_varndims(dataSet.NcId, varid, out ndims);
            NetCDFDataSet.HandleResult(res);

            dimIds = new int[ndims];

            // About variable
            res = NetCDF.nc_inq_var(dataSet.NcId, varid, out name, out ncType, out ndims, dimIds, out natts);
            NetCDFDataSet.HandleResult(res);

            // Dimensions names
            string[] dims = new string[ndims];
            for (int i = 0; i < ndims; i++)
            {
                string dimName;
                res = NetCDF.nc_inq_dimname(dataSet.NcId, dimIds[i], out dimName);
                NetCDFDataSet.HandleResult(res);

                dims[i] = dimName.ToString();
            }

#if DEBUG
            StringBuilder msg = new StringBuilder();
            for (int i = 0; i < dims.Length; i++)
            {
                msg.Append(dims[i]);
                if (i < dims.Length - 1)
                {
                    msg.Append(',');
                }
            }
            Debug.WriteLineIf(NetCDFDataSet.TraceNetCDFDataSet.TraceInfo, String.Format("Variable {0}: {1} dimensions ({2}), {3} attributes.",
                                                                                        name, ndims, msg.ToString(), natts));
#endif

            var var = new NetCdfVariable <DataType>(dataSet, varid, name.ToString(), dims);
            if (var.Rank > 0 && var.changes != null)
            {
                // Providing correct "proposed" shape taken from the input file
                int[] shape = var.ReadShape();
                if (shape == null)
                {
                    shape = new int[dims.Length];
                }
                Rectangle   ar    = new Rectangle(new int[dims.Length], shape);
                DataChanges oldch = var.changes;
                DataChanges newch = new DataChanges(oldch.ChangeSet, oldch.InitialSchema, oldch.MetadataChanges,
                                                    oldch.CoordinateSystems,
                                                    shape, ar, oldch.Data);
                var.changes = newch;
            }
            return(var);
        }
 private NetCdfVariable(NetCDFDataSet dataSet, int varid, string name, string[] dims) :
     this(dataSet, varid, name, dims, true)
 {
 }
        internal static NetCdfVariable <DataType> Create(NetCDFDataSet dataSet, string name, string[] dims)
        {
            if (dims == null)             // scalar variable
            {
                dims = new string[0];
            }

            int res;

            /* Getting exsting dims and creating new */
            int[] dimids = new int[dims.Length];
            for (int i = 0; i < dims.Length; i++)
            {
                int id;
                res = NetCDF.nc_inq_dimid(dataSet.NcId, dims[i], out id);
                if (res == (int)NetCDF.ResultCode.NC_NOERR)
                {
                    dimids[i] = id;
                }
                else if (res == (int)NetCDF.ResultCode.NC_EBADDIM)
                {
                    // Creating new dimension
                    res = NetCDF.nc_def_dim(dataSet.NcId, dims[i], new IntPtr(NetCDF.NC_UNLIMITED), out id);
                    NetCDFDataSet.HandleResult(res);
                    dimids[i] = id;
                }
                else
                {
                    NetCDFDataSet.HandleResult(res);
                }
            }

            /* Creating variable */
            int varid;

            string nc_name = GetNetCDFName(name);

            if (nc_name != name)
            {
                Debug.WriteLineIf(NetCDFDataSet.TraceNetCDFDataSet.TraceVerbose, "NetCDF: name has illegal chars; internal variable name is " + nc_name);
            }

            res = NetCDF.nc_def_var(dataSet.NcId, nc_name, NetCDF.GetNcType(typeof(DataType)), dimids.Length, dimids, out varid);
            for (int count = 1; res == (int)NetCDF.ResultCode.NC_ENAMEINUSE;)
            {
                // Keep trying to create variable with different names
                res = NetCDF.nc_def_var(dataSet.NcId, String.Format("{0}_{1}", nc_name, count++), NetCDF.GetNcType(typeof(DataType)), dimids.Length, dimids, out varid);
            }
            NetCDFDataSet.HandleResult(res);

            // Non scalar variables can be compressed.
            // It is regulated by the uri parameter "deflate".
            if (dims.Length > 0)
            {
                if (dataSet.Deflate == DeflateLevel.Off)
                {
                    res = NetCDF.nc_def_var_deflate(dataSet.NcId, varid, 0, 0, 0);
                }
                else
                {
                    res = NetCDF.nc_def_var_deflate(dataSet.NcId, varid, 0, 1, (int)dataSet.Deflate);
                }
                NetCDFDataSet.HandleResult(res);
            }

            if (dims.Length > 0)
            {
                IntPtr[] chunksizes = new IntPtr[dims.Length];

                //int chunk = Math.Min(1000, 100000 / Pow10(dims.Length - 1));
                int chunk;
                switch (dims.Length)
                {
                case 1: chunk = 1000000; break;

                case 2: chunk = 1000; break;

                case 3: chunk = 100; break;

                default: chunk = 10; break;
                }

                if (dims.Length >= 6)
                {
                    chunk = 5;
                }
                else if (dims.Length >= 9)                 // found experimentally
                {
                    chunk = 1;
                }

                //StringBuilder sbChunk = new StringBuilder();
                //sbChunk.Append("Chunk sizes for rank ").Append(dims.Length).Append(": ");
                for (int i = 0; i < dims.Length; i++)
                {
                    //sbChunk.Append(chunk).Append(",");
                    chunksizes[i] = new IntPtr(chunk);                     // TODO: need for an algorithm of chunk size selection
                }
                //Debug.WriteLine(sbChunk.ToString());

                res = NetCDF.nc_def_var_chunking(dataSet.NcId, varid, 0, chunksizes);
                NetCDFDataSet.HandleResult(res);
            }

            if (typeof(DataType) == typeof(DateTime))
            {
                NetCDFDataSet.NcPutAttText(dataSet.NcId, varid, "Units", NetCDFDataSet.dateTimeUnits);
            }
            else if (typeof(DataType) == typeof(bool))
            {
                NetCDFDataSet.NcPutAttText(dataSet.NcId, varid, AttributeTypeMap.AttributeVarSpecialType, typeof(bool).ToString());
            }

            return(new NetCdfVariable <DataType>(dataSet, varid, name, dims));
        }