2015-01-16 2 views
1

Это мой первый вопрос:Как читать NetCDF «глобальный атрибут» в C++

Я пытаюсь читать «глобальные атрибуты» из NetCDF файла (используя ++ унаследованного API C). Под «глобальным атрибутом» я подразумеваю атрибут, который был добавлен в NcFile, а не в NcVar.

Для большинства вещей «Example netCDF programs» полезны - но нет примера для «глобальных атрибутов».

проконсультировавшись с "netcdfcpp.h" Я нахожу несколько вещей:

  • NcFile имеет функцию-член: NcAtt* get_att(NcToken) const;
  • NcAtt профиль не имеет открытый конструктор
  • NcAtt дружит с NcFile: friend class NcFile;
  • У NcAtt есть частный конструктор: NcAtt(NcFile*, NcToken);
  • NcAtt имеет общественное назначение NcValues* values(void) const;
  • NcValues ​​имеет API, определенный через ncvalues.h заголовок

Мои кодирования навыки недостаточны, чтобы понять, как я вернусь в строке/INT/поплавка хранится как NcValue, в классе NcAtt в NcFile.

Прилагается пример кода моей проблемы «NetCDF_test.cpp», причем критическая часть отсутствует в реализации функции «LoadNetCDF».

Код компилируется нормально с: (редактирование: также, "TestFile.nc" создан правильно)

g++ -c NetCDF_test.cpp -o NetCDF_test.o

g++ -o NCTEST NetCDF_test.o -lnetcdf_c++ -lnetcdf

Пример кода:

#include <iostream> // provides screen output (i.e. std::cout<<) 
#include <netcdfcpp.h> 

struct MyStructure { 
    std::string MyString; 
    int MyInt; 
    float MyFloat; 

    MyStructure();  // default constructor 
    int SaveNetCDF(std::string); // Save the struct content to "global attributes" in NetCDF 
    int LoadNetCDF(std::string); // Load the struct content from "global attributes" in NetCDF 

}; 

MyStructure::MyStructure(void) 
{ 
    MyString = "TestString"; 
    MyInt = 123; 
    MyFloat = 1.23; 
} 

int MyStructure::SaveNetCDF(std::string OUTPUT_FILENAME) 
{ 
    NcError err(NcError::silent_nonfatal); 
    static const int NC_ERR = 2; 
    NcFile NetCDF_File(OUTPUT_FILENAME.c_str(), NcFile::Replace); 
    if(!NetCDF_File.is_valid()) {return NC_ERR;} 

    if(!(NetCDF_File.add_att("MyString",MyString.c_str()))) {return NC_ERR;} 
    if(!(NetCDF_File.add_att("MyInt",MyInt))) {return NC_ERR;} 
    if(!(NetCDF_File.add_att("MyFloat",MyFloat))) {return NC_ERR;} 

    return 0; 
} 

int MyStructure::LoadNetCDF(std::string INPUT_FILENAME) 
{ 

    NcError err(NcError::silent_nonfatal); 
    static const int NC_ERR = 2; 

    NcFile NetCDF_File(INPUT_FILENAME.c_str(), NcFile::ReadOnly); 
    if(!NetCDF_File.is_valid()) {return NC_ERR;} 

    // ???? This is where I am stuck. 
    // How do I read the global attribute from the NetCDF_File ?? 
    return 0; 
} 


int main() 
{ 
    std::cout<< "START OF TEST.\n"; 

    MyStructure StructureInstance; // datamembers initialized by constructor 
    StructureInstance.SaveNetCDF("TestFile.nc"); 

    StructureInstance.MyString = "Change string for sake of testing"; 
    StructureInstance.MyInt = -987; 
    StructureInstance.MyFloat = -9.87; 

    StructureInstance.LoadNetCDF("TestFile.nc"); // data members are supposed to be read from file 

    std::cout<< "Now the data members of StructureInstance should be TestString, 123, and 1.23\n"; 
    std::cout<< StructureInstance.MyString << " ; " << StructureInstance.MyInt << " ; " << StructureInstance.MyFloat <<"\n"; 
    std::cout<< "END OF TEST.\n"; 
} 

ответ

1

Большое спасибо Роб Латам за ссылки на комментировал описание API NetCDF (устаревший C++).С информацией, предоставленной там я был в состоянии понять это:

NcAtt inherents образует NcTypedComponent набор функций-членов для доступа к данным, хранящимся в пределах заданного NcAtt: (Int N == п-го элемента)

  • ncbyte as_ncbyte(int n) const
  • char as_char(int n) const
  • short as_short(int n) const
  • int as_int(int n) const
  • nclong as_nclong(int n) const // deprecated
  • long as_long(int n) const
  • float as_float(int n) const
  • double as_double(int n) const
  • char* as_string(int n) const

Но все-таки, конструктор NcAtt является приватным и единственной точкой доступа к существующему NcAtt через функции члена NcFile NcVar* get_var(NcToken name) const - - который возвращает только указатель. Таким образом, прямое использование не работает:

int MyInt = MyNcFile.get_att("MyInt").as_int(0); // DOES NOT COMPILE

Однако разыменования указателя, возвращенное get_att делает трюк.

int MyInt = (*MyNcFile.get_att("MyInt")).as_int(0); // WORKS

Для полноты картины я включаю ниже реализации MyStructure::LoadNetCDF на примере кода моего первоначального вопроса.

int MyStructure::LoadNetCDF(std::string INPUT_FILENAME) 
{ 
    NcError err(NcError::silent_nonfatal); 
    static const int NC_ERR = 2; 

    NcFile NetCDF_File(INPUT_FILENAME.c_str(), NcFile::ReadOnly); 
    if(!NetCDF_File.is_valid()) {return NC_ERR;} 

    // NcAtt constructor is private, but one can obtain the pointer to an existing NcAtt 
    NcAtt* PointerToMyIntNcAtt = NetCDF_File.get_att("MyInt"); 
    // Now, using the dereferencing operator one has access to the member functions that NcAtt inherents from NcTypedComponent 
    if(!(*PointerToMyIntNcAtt).is_valid()) {return NC_ERR;} 
    std::cout<< "Is MyInt a valid NcAtt? "<< (*PointerToMyIntNcAtt).is_valid()<<"\n"; 

    // The concise way of writing the access to NetCDF "global attributes"" of type int/float/string 
    MyInt = (*NetCDF_File.get_att("MyInt")).as_int(0); 
    MyFloat = (*NetCDF_File.get_att("MyFloat")).as_float(0); 
    MyString = (*NetCDF_File.get_att("MyString")).as_string(0); 

    return 0; 
} 
+0

Разве вы не можете заменить '(* NetCDF_File) .as_int (0)' с 'NetCDF_File-> as_int (0)'? – DopplerShift

+0

Вот как читать атрибуты, связанные с NcVar, я верю, но он не работает с «глобальными атрибутами», поскольку оператор, по-видимому, не реализован. Когда я компилирую с помощью оператора «->», получаем следующую ошибку: 'error: base operand of '->' имеет тип не указателя 'NcFile'' – Mathis

+0

Ooops, который должен быть:' NetCDF_File.get_att («MyInt») -> as_int (0) '... или это не удается? – DopplerShift

1

Это довольно четко изложено в руководстве пользователя C++: http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-cxx/Class-NcAtt.html#Class-NcAtt

«Поскольку атрибуты связаны только с открытыми файлами netCDF, для этого класса нет общих конструкторов. Функции-члены Использование по NcFile и NcVar, чтобы получить атрибуты NetCDF или добавлять новые атрибуты.»

глобальные атрибуты атрибуты в файле (в отличие от атрибутов переменных, которые, ну, атрибуты переменной)

NetCDF_File. num_atts() возвращает сколько глобальные атрибуты. в get_att() методы (перегруженные различными способами) получит вам атрибут.

консультируйтесь http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-cxx/Class-NcFile.html#Class-NcFile

Смежные вопросы