如何使用C#和Microsoft Scientific Data Set从NetCDF文件中提取数据?

时间:2017-09-10 21:44:07

标签: c# csv netcdf

我正在尝试使用Microsoft's Scientific Data Set libraries (SDS)从NetCDF文件中提取数据。我只能使用MS SDS和C#。我不是一个贸易程序员,所以我很难让基础工作。首先,我想编写一个简单的脚本来提取数据并将其写入.csv文件。 使用introduction doc和codeplex教程。我试着编写一个简单的C#控制台应用程序,它只读取文件并将其写入控制台或理想情况下写入.csv文件。

使用SDS 1.3命令行我可以查看我的测试文件的内容:

D:\NetCDF>sds list test.nc
[2] ACPR of type Single (Time:85) (south_north:213) (west_east:165)
[1] Times of type SByte (Time:85) (DateStrLen:19)
D:\NetCDF>

我的脚本如下所示:

using System;
using System.IO;
using sds = Microsoft.Research.Science.Data;
using Microsoft.Research.Science.Data.Imperative;


namespace NetCDFConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            /// Gets the path to the NetCDF file to be used as a data source.
            var dataset = sds.DataSet.Open("D:\\NetCDF\\test.nc?openMode=readOnly");

            SByte[,] times = dataset.GetData<SByte[,]>("Times");
            //Int32[,] times = dataset.GetData<Int32[,]>("Times");

            //Single[] longitudes = dataset.GetData<Single[]>("west_east");
            //var latitudes = dataset.GetData<Single[]>("south_north");
            Single[,,] dataValues = dataset.GetData<Single[,,]>("ACPR");

            for (int iTime = 50; iTime < 60; iTime++)
            {
                for (int iLongitude = 130; iLongitude < 150; iLongitude++)
                 {
                    for (int iLatitude = 130; iLatitude < 140; iLatitude++)
                    {
                        // write output data
                        float thisValue = dataValues[iTime,iLatitude,iLongitude];

                        Console.WriteLine(iTime);
                        Console.WriteLine(iLatitude);
                        Console.WriteLine(iLongitude);
                        Console.WriteLine(thisValue);

                    }
                 }
            }
        }
    }
} 

如果我注释掉var Times ...那么它就会运行。但我正在努力让SDS读取Time Dimension。如果我使用SByte,它会抱怨变量不存在。如果我使用Int32,它会抱怨转换为字符串。

System.InvalidOperationException was unhandled
  HResult=-2146233079
  Message=Requested variable does not exist in the data set
  Source=ScientificDataSet
  StackTrace:
       at Microsoft.Research.Science.Data.Imperative.DataSetExtensions.FindVariable(DataSet dataset, Func`2 predicate)
       at Microsoft.Research.Science.Data.Imperative.DataSetExtensions.GetData[D](DataSet dataset, String variableName)
       at NetCDFConsoleApp.Program.Main(String[] args) in \\gdc-fs01\user$\prm\Visual Studio 2015\projects\NetCDFConsoleApp\Program.cs:line 16
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

我错过了什么?

1 个答案:

答案 0 :(得分:1)

我想我已经解决了这个难题。问题是第二个变量是空的。我不确定这是不是偶然或设计。

我找到了数据应该在元数据字段中开始的日期。我现在修改了我的代码,以便它检索它,然后将它全部写入控制台。

using System;
using System.IO;
using sds = Microsoft.Research.Science.Data;
using Microsoft.Research.Science.Data.Imperative;


namespace NetCDFConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            /// Gets the path to the NetCDF file to be used as a data source.
            var dataset = sds.DataSet.Open("D:\\NetCDF\\test.nc?openMode=readOnly");

            string dt = (string)dataset.Metadata["START_DATE"];

            Single[,,] dataValues = dataset.GetData<Single[,,]>("ACPR");

            for (int iTime = 50; iTime < 60; iTime++)
            {
                for (int iLongitude = 130; iLongitude < 150; iLongitude++)
                {
                    for (int iLatitude = 130; iLatitude < 140; iLatitude++)
                    {
                        // write output data
                        float thisValue = dataValues[iTime,iLatitude,iLongitude];                                                
                        Console.WriteLine(dt.ToString() + ',' + iTime.ToString() + ',' + iLatitude.ToString() + ',' + iLongitude.ToString() + ',' + thisValue.ToString());

                    }                 
                }
            }            
            Console.ReadLine();
        }           
    }
}             

我真的很挣扎,所以我分享这个,希望它对其他人有用。

我真正觉得有用的一件事是discussion tab on Codeplex,因为它有很多有用的代码片段。