Feature/eckit geo (#275)

* eckit::geo iterator
This commit is contained in:
Pedro Maciel 2024-12-03 19:20:47 +00:00 committed by GitHub
parent db62ed657c
commit 68f347e79f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 1394 additions and 3 deletions

View File

@ -112,6 +112,18 @@ ecbuild_add_option( FEATURE GEOGRAPHY
DESCRIPTION "Support for Geoiterator and nearest neighbour" DESCRIPTION "Support for Geoiterator and nearest neighbour"
DEFAULT ON ) DEFAULT ON )
ecbuild_add_option( FEATURE ECKIT_GEO
DESCRIPTION "Support for Geoiterator and nearest neighbour (additional backend)"
CONDITION ENABLE_GEOGRAPHY
DEFAULT OFF )
if( eccodes_HAVE_ECKIT_GEO AND NOT TARGET eckit_geo )
ecbuild_find_package(NAME eckit VERSION 1.27 REQUIRED)
if( NOT TARGET eckit_geo )
ecbuild_critical("eckit has not been built with ECKIT_GEO enabled")
endif()
endif()
ecbuild_add_option( FEATURE JPG ecbuild_add_option( FEATURE JPG
DESCRIPTION "Support for JPG decoding/encoding" DESCRIPTION "Support for JPG decoding/encoding"
DEFAULT ON ) DEFAULT ON )
@ -485,7 +497,7 @@ ecbuild_pkgconfig(
IGNORE_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS} ${NUMPY_INCLUDE_DIRS} ${NETCDF_INCLUDE_DIRS} IGNORE_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS} ${NUMPY_INCLUDE_DIRS} ${NETCDF_INCLUDE_DIRS}
VARIABLES HAVE_MEMFS HAVE_GEOGRAPHY HAVE_JPEG HAVE_LIBJASPER HAVE_LIBOPENJPEG VARIABLES HAVE_MEMFS HAVE_GEOGRAPHY HAVE_JPEG HAVE_LIBJASPER HAVE_LIBOPENJPEG
HAVE_ECCODES_THREADS HAVE_ECCODES_OMP_THREADS HAVE_ECCODES_THREADS HAVE_ECCODES_OMP_THREADS
HAVE_NETCDF HAVE_FORTRAN HAVE_PNG HAVE_AEC HAVE_NETCDF HAVE_FORTRAN HAVE_PNG HAVE_AEC HAVE_ECKIT_GEO
) )
if( HAVE_FORTRAN ) if( HAVE_FORTRAN )
ecbuild_pkgconfig( ecbuild_pkgconfig(
@ -497,7 +509,7 @@ if( HAVE_FORTRAN )
${PYTHON_INCLUDE_DIRS} ${NUMPY_INCLUDE_DIRS} ${NETCDF_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS} ${NUMPY_INCLUDE_DIRS} ${NETCDF_INCLUDE_DIRS}
VARIABLES HAVE_MEMFS HAVE_GEOGRAPHY HAVE_JPEG HAVE_LIBJASPER HAVE_LIBOPENJPEG VARIABLES HAVE_MEMFS HAVE_GEOGRAPHY HAVE_JPEG HAVE_LIBJASPER HAVE_LIBOPENJPEG
HAVE_ECCODES_THREADS HAVE_ECCODES_OMP_THREADS HAVE_ECCODES_THREADS HAVE_ECCODES_OMP_THREADS
HAVE_NETCDF HAVE_PNG HAVE_AEC HAVE_NETCDF HAVE_PNG HAVE_AEC HAVE_ECKIT_GEO
) )
endif() endif()

View File

@ -114,6 +114,7 @@
#cmakedefine HAVE_NETCDF #cmakedefine HAVE_NETCDF
#cmakedefine HAVE_GEOGRAPHY #cmakedefine HAVE_GEOGRAPHY
#cmakedefine HAVE_ECKIT_GEO
#cmakedefine HAVE_MEMFS #cmakedefine HAVE_MEMFS
#cmakedefine HAVE_FORTRAN #cmakedefine HAVE_FORTRAN

View File

@ -411,6 +411,15 @@ if( HAVE_MEMFS )
list(APPEND ECCODES_EXTRA_LIBRARIES eccodes_memfs) list(APPEND ECCODES_EXTRA_LIBRARIES eccodes_memfs)
endif() endif()
if( eccodes_HAVE_GEOGRAPHY AND eccodes_HAVE_ECKIT_GEO )
list( APPEND eccodes_src_files
eccodes/geo/GeoIterator.cc
eccodes/geo/GeoIterator.h
eccodes/geo/GribSpec.cc
eccodes/geo/GribSpec.h )
list( APPEND ECCODES_EXTRA_LIBRARIES eckit_geo )
endif()
ecbuild_add_library( TARGET eccodes ecbuild_add_library( TARGET eccodes
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/grib_api_version.cc SOURCES ${CMAKE_CURRENT_BINARY_DIR}/grib_api_version.cc
# griby.cc gribl.cc # griby.cc gribl.cc

View File

@ -0,0 +1,104 @@
/*
* (C) Copyright 2024- ECMWF.
*
* This software is licensed under the terms of the Apache Licence Version 2.0
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
*
* In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
* virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
*/
#include "eccodes/geo/GeoIterator.h"
#include "eckit/exception/Exceptions.h"
#include "eccodes/geo/GribSpec.h"
namespace eccodes::geo
{
GeoIterator::GeoIterator(grib_handle* h, unsigned long flags) :
spec_(new GribSpec(h)), grid_(eckit::geo::GridFactory::build(*spec_)), iter_(grid_->cbegin().release()), end_(grid_->cend().release())
{
h_ = h;
class_name_ = "geo_iterator";
flags_ = flags;
Assert(h_ != nullptr);
CODES_CHECK(codes_get_size(h_, "values", &nv_), "");
Assert(nv_ > 0);
data_ = (flags_ & GRIB_GEOITERATOR_NO_VALUES) ? nullptr : static_cast<double*>(grib_context_malloc(h_->context, nv_ * sizeof(double)));
Assert(data_ != nullptr);
auto size = nv_;
CODES_CHECK(codes_get_double_array(h_, "values", data_, &size), "");
Assert(nv_ == size);
}
int GeoIterator::init(grib_handle*, grib_arguments*)
{
NOTIMP;
}
int GeoIterator::next(double* lat, double* lon, double* val) const
{
if (iter_ == end_) {
return 0; // (false)
}
const auto p = *iter_;
const auto& q = std::get<eckit::geo::PointLonLat>(p);
*lat = q.lat;
*lon = q.lon;
if (val != nullptr && data_ != nullptr) {
*val = data_[iter_->index()];
}
++iter_;
return 1; // (true)
}
int GeoIterator::previous(double*, double*, double*) const
{
return GRIB_NOT_IMPLEMENTED;
}
int GeoIterator::reset()
{
iter_.reset(grid_->cbegin().release());
return GRIB_SUCCESS;
}
int GeoIterator::destroy()
{
if (data_ != nullptr) {
grib_context_free(h_->context, data_);
}
return Iterator::destroy();
}
bool GeoIterator::has_next() const
{
return iter_ != end_;
}
geo_iterator::Iterator*
GeoIterator::create() const
{
return new GeoIterator{ h_, flags_ };
}
} // namespace eccodes::geo

View File

@ -0,0 +1,51 @@
/*
* (C) Copyright 2024- ECMWF.
*
* This software is licensed under the terms of the Apache Licence Version 2.0
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
*
* In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
* virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
*/
#pragma once
#include <memory>
#include "eckit/geo/Grid.h"
// eccodes macros conflict with eckit
#ifdef Assert
#undef Assert
#endif
#include "geo_iterator/grib_iterator.h"
namespace eccodes::geo
{
class GeoIterator : public geo_iterator::Iterator
{
public:
explicit GeoIterator(grib_handle*, unsigned long flags);
private:
std::unique_ptr<const eckit::geo::Spec> spec_;
std::unique_ptr<const eckit::geo::Grid> grid_;
mutable eckit::geo::Grid::Iterator iter_;
eckit::geo::Grid::Iterator end_;
int init(grib_handle*, grib_arguments*) override;
int next(double* lat, double* lon, double* val) const override;
int previous(double* lat, double* lon, double* val) const override;
int reset() override;
int destroy() override;
bool has_next() const override;
geo_iterator::Iterator* create() const override;
};
} // namespace eccodes::geo

1104
src/eccodes/geo/GribSpec.cc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,63 @@
/*
* (C) Copyright 2024- ECMWF.
*
* This software is licensed under the terms of the Apache Licence Version 2.0
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
*
* In applying this licence, ECMWF does not waive the privileges and immunities
* granted to it by virtue of its status as an intergovernmental organisation nor
* does it submit to any jurisdiction.
*/
#pragma once
#include "eccodes.h"
#include <string>
#include <vector>
#include "eckit/geo/Spec.h"
#include "eckit/geo/spec/Custom.h"
namespace eccodes::geo
{
bool codes_check_error(int e, const char* call);
class GribSpec final : public eckit::geo::Spec
{
public:
explicit GribSpec(codes_handle*);
bool has(const std::string& name) const override;
bool get(const std::string& name, std::string& value) const override;
bool get(const std::string& name, bool& value) const override;
bool get(const std::string& name, int& value) const override;
bool get(const std::string& name, long& value) const override;
bool get(const std::string& name, long long& value) const override;
bool get(const std::string& name, size_t& value) const override;
bool get(const std::string& name, float& value) const override;
bool get(const std::string& name, double& value) const override;
bool get(const std::string& name, std::vector<int>& value) const override;
bool get(const std::string& name, std::vector<long>& value) const override;
bool get(const std::string& name, std::vector<long long>& value) const override;
bool get(const std::string& name, std::vector<size_t>& value) const override;
bool get(const std::string& name, std::vector<float>& value) const override;
bool get(const std::string& name, std::vector<double>& value) const override;
bool get(const std::string& name, std::vector<std::string>& value) const override;
private:
mutable eckit::geo::spec::Custom cache_;
codes_handle* handle_;
void json(eckit::JSON&) const final;
};
} // namespace eccodes::geo

View File

@ -12,6 +12,19 @@
* Jean Baptiste Filippi - 01.11.2005 * * Jean Baptiste Filippi - 01.11.2005 *
***************************************************************************/ ***************************************************************************/
#include "eccodes_config.h"
#if defined(HAVE_ECKIT_GEO)
#include "eckit/runtime/Main.h"
#include "eccodes/geo/GeoIterator.h"
// eccodes macros conflict with eckit
#ifdef Assert
#undef Assert
#endif
#endif
#include "grib_iterator.h" #include "grib_iterator.h"
#include "grib_iterator_factory.h" #include "grib_iterator_factory.h"
#include "accessor/grib_accessor_class_iterator.h" #include "accessor/grib_accessor_class_iterator.h"
@ -95,7 +108,29 @@ int grib_iterator_destroy(grib_context* c, grib_iterator* i)
grib_iterator* grib_iterator_new(const grib_handle* ch, unsigned long flags, int* error) grib_iterator* grib_iterator_new(const grib_handle* ch, unsigned long flags, int* error)
{ {
grib_iterator* i = (grib_iterator*)grib_context_malloc_clear(ch->context, sizeof(grib_iterator)); grib_iterator* i = (grib_iterator*)grib_context_malloc_clear(ch->context, sizeof(grib_iterator));
#if defined(HAVE_ECKIT_GEO)
static const auto* eckit_geo = codes_getenv("ECCODES_ECKIT_GEO");
if (eckit_geo != nullptr && strcmp(eckit_geo, "1") == 0) {
struct InitMain
{
InitMain()
{
if (!eckit::Main::ready()) {
static char* argv[]{ const_cast<char*>("grib_iterator_new") };
eckit::Main::initialise(1, argv);
}
}
} static const init_main;
i->iterator = new eccodes::geo::GeoIterator(const_cast<grib_handle*>(ch), flags);
}
else
#endif
{
i->iterator = eccodes::geo_iterator::gribIteratorNew(ch, flags, error); i->iterator = eccodes::geo_iterator::gribIteratorNew(ch, flags, error);
}
if (!i->iterator) { if (!i->iterator) {
grib_context_free(ch->context, i); grib_context_free(ch->context, i);
return NULL; return NULL;

View File

@ -24,6 +24,9 @@ ecbuild_add_library( TARGET ecc_tools
NOINSTALL NOINSTALL
SOURCES ${ecc_tools_sources} SOURCES ${ecc_tools_sources}
PRIVATE_LIBS eccodes ) PRIVATE_LIBS eccodes )
if( eccodes_HAVE_ECKIT_GEO )
target_link_libraries( ecc_tools PRIVATE eckit )
endif()
# tools binaries # tools binaries
list( APPEND ecc_tools_binaries list( APPEND ecc_tools_binaries

View File

@ -9,9 +9,14 @@
*/ */
#include "grib_tools.h" #include "grib_tools.h"
#include <stdlib.h> #include <stdlib.h>
#include <string> #include <string>
#ifdef HAVE_ECKIT_GEO
#include "eckit/runtime/Main.h"
#endif
#if HAVE_LIBJASPER #if HAVE_LIBJASPER
/* Remove compiler warnings re macros being redefined */ /* Remove compiler warnings re macros being redefined */
#undef PACKAGE_BUGREPORT #undef PACKAGE_BUGREPORT
@ -141,6 +146,10 @@ static grib_handle* grib_handle_new_from_file_x(grib_context* c, FILE* f, int mo
int grib_tool(int argc, char** argv) int grib_tool(int argc, char** argv)
{ {
#ifdef HAVE_ECKIT_GEO
eckit::Main::initialise(argc, argv);
#endif
int ret = 0; int ret = 0;
int i = 0; int i = 0;
grib_context* c = grib_context_get_default(); grib_context* c = grib_context_get_default();