mirror of https://github.com/ecmwf/eccodes.git
added grib_merge.c tool
This commit is contained in:
parent
70f24489a4
commit
7400f09067
|
@ -1,40 +1,365 @@
|
||||||
|
Installation Instructions
|
||||||
|
*************************
|
||||||
|
|
||||||
The grib_api installation is based on the standard configure utility.
|
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||||
It is tested on several platforms and with several compilers. However for some platforms
|
2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||||
modifications to the installation engine may be required. If you encounter any problem
|
|
||||||
during the installation procedure please send an e-mail with your problem to
|
|
||||||
Software.Support@ecmwf.int.
|
|
||||||
|
|
||||||
The only required package for a standard installation is jasper which enables the jpeg2000
|
Copying and distribution of this file, with or without modification,
|
||||||
packing/unpacking algorithm.
|
are permitted in any medium without royalty provided the copyright
|
||||||
It is possible to build grib_api without jasper, by using the --disable-jpeg configure option,
|
notice and this notice are preserved. This file is offered as-is,
|
||||||
but to install a fully functional library, its download is recommended.
|
without warranty of any kind.
|
||||||
|
|
||||||
|
Basic Installation
|
||||||
|
==================
|
||||||
|
|
||||||
Standard Installation
|
Briefly, the shell commands `./configure; make; make install' should
|
||||||
|
configure, build, and install this package. The following
|
||||||
|
more-detailed instructions are generic; see the `README' file for
|
||||||
|
instructions specific to this package. Some packages provide this
|
||||||
|
`INSTALL' file but do not implement all of the features documented
|
||||||
|
below. The lack of an optional feature in a given package is not
|
||||||
|
necessarily a bug. More recommendations for GNU packages can be found
|
||||||
|
in *note Makefile Conventions: (standards)Makefile Conventions.
|
||||||
|
|
||||||
|
The `configure' shell script attempts to guess correct values for
|
||||||
|
various system-dependent variables used during compilation. It uses
|
||||||
|
those values to create a `Makefile' in each directory of the package.
|
||||||
|
It may also create one or more `.h' files containing system-dependent
|
||||||
|
definitions. Finally, it creates a shell script `config.status' that
|
||||||
|
you can run in the future to recreate the current configuration, and a
|
||||||
|
file `config.log' containing compiler output (useful mainly for
|
||||||
|
debugging `configure').
|
||||||
|
|
||||||
|
It can also use an optional file (typically called `config.cache'
|
||||||
|
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||||
|
the results of its tests to speed up reconfiguring. Caching is
|
||||||
|
disabled by default to prevent problems with accidental use of stale
|
||||||
|
cache files.
|
||||||
|
|
||||||
|
If you need to do unusual things to compile the package, please try
|
||||||
|
to figure out how `configure' could check whether to do them, and mail
|
||||||
|
diffs or instructions to the address given in the `README' so they can
|
||||||
|
be considered for the next release. If you are using the cache, and at
|
||||||
|
some point `config.cache' contains results you don't want to keep, you
|
||||||
|
may remove or edit it.
|
||||||
|
|
||||||
|
The file `configure.ac' (or `configure.in') is used to create
|
||||||
|
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||||
|
you want to change it or regenerate `configure' using a newer version
|
||||||
|
of `autoconf'.
|
||||||
|
|
||||||
|
The simplest way to compile this package is:
|
||||||
|
|
||||||
|
1. `cd' to the directory containing the package's source code and type
|
||||||
|
`./configure' to configure the package for your system.
|
||||||
|
|
||||||
|
Running `configure' might take a while. While running, it prints
|
||||||
|
some messages telling which features it is checking for.
|
||||||
|
|
||||||
|
2. Type `make' to compile the package.
|
||||||
|
|
||||||
|
3. Optionally, type `make check' to run any self-tests that come with
|
||||||
|
the package, generally using the just-built uninstalled binaries.
|
||||||
|
|
||||||
|
4. Type `make install' to install the programs and any data files and
|
||||||
|
documentation. When installing into a prefix owned by root, it is
|
||||||
|
recommended that the package be configured and built as a regular
|
||||||
|
user, and only the `make install' phase executed with root
|
||||||
|
privileges.
|
||||||
|
|
||||||
|
5. Optionally, type `make installcheck' to repeat any self-tests, but
|
||||||
|
this time using the binaries in their final installed location.
|
||||||
|
This target does not install anything. Running this target as a
|
||||||
|
regular user, particularly if the prior `make install' required
|
||||||
|
root privileges, verifies that the installation completed
|
||||||
|
correctly.
|
||||||
|
|
||||||
|
6. You can remove the program binaries and object files from the
|
||||||
|
source code directory by typing `make clean'. To also remove the
|
||||||
|
files that `configure' created (so you can compile the package for
|
||||||
|
a different kind of computer), type `make distclean'. There is
|
||||||
|
also a `make maintainer-clean' target, but that is intended mainly
|
||||||
|
for the package's developers. If you use it, you may have to get
|
||||||
|
all sorts of other programs in order to regenerate files that came
|
||||||
|
with the distribution.
|
||||||
|
|
||||||
|
7. Often, you can also type `make uninstall' to remove the installed
|
||||||
|
files again. In practice, not all packages have tested that
|
||||||
|
uninstallation works correctly, even though it is required by the
|
||||||
|
GNU Coding Standards.
|
||||||
|
|
||||||
|
8. Some packages, particularly those that use Automake, provide `make
|
||||||
|
distcheck', which can by used by developers to test that all other
|
||||||
|
targets like `make install' and `make uninstall' work correctly.
|
||||||
|
This target is generally not run by end users.
|
||||||
|
|
||||||
|
Compilers and Options
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
1. Download grib_api from https://software.ecmwf.int/wiki/display/GRIB/Releases.
|
Some systems require unusual options for compilation or linking that
|
||||||
2. Unpack distribution:
|
the `configure' script does not know about. Run `./configure --help'
|
||||||
|
for details on some of the pertinent environment variables.
|
||||||
|
|
||||||
> gunzip grib_api-X.tar.gz
|
You can give `configure' initial values for configuration parameters
|
||||||
> tar xf grib_api-X.tar
|
by setting variables in the command line or in the environment. Here
|
||||||
|
is an example:
|
||||||
|
|
||||||
3. Create the directory where to install grib_api say grib_api_dir
|
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||||
|
|
||||||
> mkdir grib_api_dir
|
*Note Defining Variables::, for more details.
|
||||||
|
|
||||||
4. Run the configure in the grib_api-X
|
Compiling For Multiple Architectures
|
||||||
|
====================================
|
||||||
|
|
||||||
> cd grib_api-X
|
You can compile the package for more than one kind of computer at the
|
||||||
> ./configure --prefix=grib_api_dir
|
same time, by placing the object files for each architecture in their
|
||||||
|
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||||
|
directory where you want the object files and executables to go and run
|
||||||
|
the `configure' script. `configure' automatically checks for the
|
||||||
|
source code in the directory that `configure' is in and in `..'. This
|
||||||
|
is known as a "VPATH" build.
|
||||||
|
|
||||||
5. make, check and install
|
With a non-GNU `make', it is safer to compile the package for one
|
||||||
|
architecture at a time in the source code directory. After you have
|
||||||
|
installed the package for one architecture, use `make distclean' before
|
||||||
|
reconfiguring for another architecture.
|
||||||
|
|
||||||
> make
|
On MacOS X 10.5 and later systems, you can create libraries and
|
||||||
...
|
executables that work on multiple system types--known as "fat" or
|
||||||
> make check
|
"universal" binaries--by specifying multiple `-arch' options to the
|
||||||
...
|
compiler but only a single `-arch' option to the preprocessor. Like
|
||||||
> make install
|
this:
|
||||||
...
|
|
||||||
|
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||||
|
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||||
|
CPP="gcc -E" CXXCPP="g++ -E"
|
||||||
|
|
||||||
|
This is not guaranteed to produce working output in all cases, you
|
||||||
|
may have to build one architecture at a time and combine the results
|
||||||
|
using the `lipo' tool if you have problems.
|
||||||
|
|
||||||
|
Installation Names
|
||||||
|
==================
|
||||||
|
|
||||||
|
By default, `make install' installs the package's commands under
|
||||||
|
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||||
|
can specify an installation prefix other than `/usr/local' by giving
|
||||||
|
`configure' the option `--prefix=PREFIX', where PREFIX must be an
|
||||||
|
absolute file name.
|
||||||
|
|
||||||
|
You can specify separate installation prefixes for
|
||||||
|
architecture-specific files and architecture-independent files. If you
|
||||||
|
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||||
|
PREFIX as the prefix for installing programs and libraries.
|
||||||
|
Documentation and other data files still use the regular prefix.
|
||||||
|
|
||||||
|
In addition, if you use an unusual directory layout you can give
|
||||||
|
options like `--bindir=DIR' to specify different values for particular
|
||||||
|
kinds of files. Run `configure --help' for a list of the directories
|
||||||
|
you can set and what kinds of files go in them. In general, the
|
||||||
|
default for these options is expressed in terms of `${prefix}', so that
|
||||||
|
specifying just `--prefix' will affect all of the other directory
|
||||||
|
specifications that were not explicitly provided.
|
||||||
|
|
||||||
|
The most portable way to affect installation locations is to pass the
|
||||||
|
correct locations to `configure'; however, many packages provide one or
|
||||||
|
both of the following shortcuts of passing variable assignments to the
|
||||||
|
`make install' command line to change installation locations without
|
||||||
|
having to reconfigure or recompile.
|
||||||
|
|
||||||
|
The first method involves providing an override variable for each
|
||||||
|
affected directory. For example, `make install
|
||||||
|
prefix=/alternate/directory' will choose an alternate location for all
|
||||||
|
directory configuration variables that were expressed in terms of
|
||||||
|
`${prefix}'. Any directories that were specified during `configure',
|
||||||
|
but not in terms of `${prefix}', must each be overridden at install
|
||||||
|
time for the entire installation to be relocated. The approach of
|
||||||
|
makefile variable overrides for each directory variable is required by
|
||||||
|
the GNU Coding Standards, and ideally causes no recompilation.
|
||||||
|
However, some platforms have known limitations with the semantics of
|
||||||
|
shared libraries that end up requiring recompilation when using this
|
||||||
|
method, particularly noticeable in packages that use GNU Libtool.
|
||||||
|
|
||||||
|
The second method involves providing the `DESTDIR' variable. For
|
||||||
|
example, `make install DESTDIR=/alternate/directory' will prepend
|
||||||
|
`/alternate/directory' before all installation names. The approach of
|
||||||
|
`DESTDIR' overrides is not required by the GNU Coding Standards, and
|
||||||
|
does not work on platforms that have drive letters. On the other hand,
|
||||||
|
it does better at avoiding recompilation issues, and works well even
|
||||||
|
when some directory options were not specified in terms of `${prefix}'
|
||||||
|
at `configure' time.
|
||||||
|
|
||||||
|
Optional Features
|
||||||
|
=================
|
||||||
|
|
||||||
|
If the package supports it, you can cause programs to be installed
|
||||||
|
with an extra prefix or suffix on their names by giving `configure' the
|
||||||
|
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||||
|
|
||||||
|
Some packages pay attention to `--enable-FEATURE' options to
|
||||||
|
`configure', where FEATURE indicates an optional part of the package.
|
||||||
|
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||||
|
is something like `gnu-as' or `x' (for the X Window System). The
|
||||||
|
`README' should mention any `--enable-' and `--with-' options that the
|
||||||
|
package recognizes.
|
||||||
|
|
||||||
|
For packages that use the X Window System, `configure' can usually
|
||||||
|
find the X include and library files automatically, but if it doesn't,
|
||||||
|
you can use the `configure' options `--x-includes=DIR' and
|
||||||
|
`--x-libraries=DIR' to specify their locations.
|
||||||
|
|
||||||
|
Some packages offer the ability to configure how verbose the
|
||||||
|
execution of `make' will be. For these packages, running `./configure
|
||||||
|
--enable-silent-rules' sets the default to minimal output, which can be
|
||||||
|
overridden with `make V=1'; while running `./configure
|
||||||
|
--disable-silent-rules' sets the default to verbose, which can be
|
||||||
|
overridden with `make V=0'.
|
||||||
|
|
||||||
|
Particular systems
|
||||||
|
==================
|
||||||
|
|
||||||
|
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
|
||||||
|
CC is not installed, it is recommended to use the following options in
|
||||||
|
order to use an ANSI C compiler:
|
||||||
|
|
||||||
|
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
|
||||||
|
|
||||||
|
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||||
|
|
||||||
|
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||||
|
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
|
||||||
|
a workaround. If GNU CC is not installed, it is therefore recommended
|
||||||
|
to try
|
||||||
|
|
||||||
|
./configure CC="cc"
|
||||||
|
|
||||||
|
and if that doesn't work, try
|
||||||
|
|
||||||
|
./configure CC="cc -nodtk"
|
||||||
|
|
||||||
|
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
|
||||||
|
directory contains several dysfunctional programs; working variants of
|
||||||
|
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
|
||||||
|
in your `PATH', put it _after_ `/usr/bin'.
|
||||||
|
|
||||||
|
On Haiku, software installed for all users goes in `/boot/common',
|
||||||
|
not `/usr/local'. It is recommended to use the following options:
|
||||||
|
|
||||||
|
./configure --prefix=/boot/common
|
||||||
|
|
||||||
|
Specifying the System Type
|
||||||
|
==========================
|
||||||
|
|
||||||
|
There may be some features `configure' cannot figure out
|
||||||
|
automatically, but needs to determine by the type of machine the package
|
||||||
|
will run on. Usually, assuming the package is built to be run on the
|
||||||
|
_same_ architectures, `configure' can figure that out, but if it prints
|
||||||
|
a message saying it cannot guess the machine type, give it the
|
||||||
|
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||||
|
type, such as `sun4', or a canonical name which has the form:
|
||||||
|
|
||||||
|
CPU-COMPANY-SYSTEM
|
||||||
|
|
||||||
|
where SYSTEM can have one of these forms:
|
||||||
|
|
||||||
|
OS
|
||||||
|
KERNEL-OS
|
||||||
|
|
||||||
|
See the file `config.sub' for the possible values of each field. If
|
||||||
|
`config.sub' isn't included in this package, then this package doesn't
|
||||||
|
need to know the machine type.
|
||||||
|
|
||||||
|
If you are _building_ compiler tools for cross-compiling, you should
|
||||||
|
use the option `--target=TYPE' to select the type of system they will
|
||||||
|
produce code for.
|
||||||
|
|
||||||
|
If you want to _use_ a cross compiler, that generates code for a
|
||||||
|
platform different from the build platform, you should specify the
|
||||||
|
"host" platform (i.e., that on which the generated programs will
|
||||||
|
eventually be run) with `--host=TYPE'.
|
||||||
|
|
||||||
|
Sharing Defaults
|
||||||
|
================
|
||||||
|
|
||||||
|
If you want to set default values for `configure' scripts to share,
|
||||||
|
you can create a site shell script called `config.site' that gives
|
||||||
|
default values for variables like `CC', `cache_file', and `prefix'.
|
||||||
|
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||||
|
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||||
|
`CONFIG_SITE' environment variable to the location of the site script.
|
||||||
|
A warning: not all `configure' scripts look for a site script.
|
||||||
|
|
||||||
|
Defining Variables
|
||||||
|
==================
|
||||||
|
|
||||||
|
Variables not defined in a site shell script can be set in the
|
||||||
|
environment passed to `configure'. However, some packages may run
|
||||||
|
configure again during the build, and the customized values of these
|
||||||
|
variables may be lost. In order to avoid this problem, you should set
|
||||||
|
them in the `configure' command line, using `VAR=value'. For example:
|
||||||
|
|
||||||
|
./configure CC=/usr/local2/bin/gcc
|
||||||
|
|
||||||
|
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||||
|
overridden in the site shell script).
|
||||||
|
|
||||||
|
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||||
|
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||||
|
|
||||||
|
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||||
|
|
||||||
|
`configure' Invocation
|
||||||
|
======================
|
||||||
|
|
||||||
|
`configure' recognizes the following options to control how it
|
||||||
|
operates.
|
||||||
|
|
||||||
|
`--help'
|
||||||
|
`-h'
|
||||||
|
Print a summary of all of the options to `configure', and exit.
|
||||||
|
|
||||||
|
`--help=short'
|
||||||
|
`--help=recursive'
|
||||||
|
Print a summary of the options unique to this package's
|
||||||
|
`configure', and exit. The `short' variant lists options used
|
||||||
|
only in the top level, while the `recursive' variant lists options
|
||||||
|
also present in any nested packages.
|
||||||
|
|
||||||
|
`--version'
|
||||||
|
`-V'
|
||||||
|
Print the version of Autoconf used to generate the `configure'
|
||||||
|
script, and exit.
|
||||||
|
|
||||||
|
`--cache-file=FILE'
|
||||||
|
Enable the cache: use and save the results of the tests in FILE,
|
||||||
|
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||||
|
disable caching.
|
||||||
|
|
||||||
|
`--config-cache'
|
||||||
|
`-C'
|
||||||
|
Alias for `--cache-file=config.cache'.
|
||||||
|
|
||||||
|
`--quiet'
|
||||||
|
`--silent'
|
||||||
|
`-q'
|
||||||
|
Do not print messages saying which checks are being made. To
|
||||||
|
suppress all normal output, redirect it to `/dev/null' (any error
|
||||||
|
messages will still be shown).
|
||||||
|
|
||||||
|
`--srcdir=DIR'
|
||||||
|
Look for the package's source code in directory DIR. Usually
|
||||||
|
`configure' can determine that directory automatically.
|
||||||
|
|
||||||
|
`--prefix=DIR'
|
||||||
|
Use DIR as the installation prefix. *note Installation Names::
|
||||||
|
for more details, including other options available for fine-tuning
|
||||||
|
the installation locations.
|
||||||
|
|
||||||
|
`--no-create'
|
||||||
|
`-n'
|
||||||
|
Run the configure checks, but stop before creating any output
|
||||||
|
files.
|
||||||
|
|
||||||
|
`configure' also accepts some other, not widely useful, options. Run
|
||||||
|
`configure --help' for more details.
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ hash_array sequences (defaultSequence,"sequence.def",tablesMasterDir,tablesLocal
|
||||||
position offsetSection3;
|
position offsetSection3;
|
||||||
section_length[3] section3Length ;
|
section_length[3] section3Length ;
|
||||||
unsigned[1] reserved = 0;
|
unsigned[1] reserved = 0;
|
||||||
unsigned[2] numberOfDataSubsets : dump;
|
unsigned[2] numberOfSubsets : dump;
|
||||||
|
|
||||||
if (section2Present && centre==98 && section2Length==52) {
|
if (section2Present && centre==98 && section2Length==52) {
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ if (section2Present && centre==98 && section2Length==52) {
|
||||||
1 = {rdbType = 8; }
|
1 = {rdbType = 8; }
|
||||||
1 = {rdbType = 12; }
|
1 = {rdbType = 12; }
|
||||||
}
|
}
|
||||||
if (isSatelliteType || numberOfDataSubsets>1) {
|
if (isSatelliteType || numberOfSubsets>1) {
|
||||||
constant isSatellite=1;
|
constant isSatellite=1;
|
||||||
} else {
|
} else {
|
||||||
constant isSatellite=0;
|
constant isSatellite=0;
|
||||||
|
@ -44,7 +44,7 @@ if (section2Present && centre==98 && section2Length==52) {
|
||||||
meta localLongitude2 bits(keyMore,0,26,-18000000,100000) : dump;
|
meta localLongitude2 bits(keyMore,0,26,-18000000,100000) : dump;
|
||||||
meta localLatitude2 bits(keyMore,32,25,-9000000,100000) : dump;
|
meta localLatitude2 bits(keyMore,32,25,-9000000,100000) : dump;
|
||||||
|
|
||||||
if (numberOfDataSubsets>255 ||
|
if (numberOfSubsets>255 ||
|
||||||
( rdbSubtype>=121 && rdbSubtype <=130 ) ||
|
( rdbSubtype>=121 && rdbSubtype <=130 ) ||
|
||||||
rdbSubtype==31) {
|
rdbSubtype==31) {
|
||||||
meta ls.umberOfObservations bits(keySat,0,16) : dump,long_type;
|
meta ls.umberOfObservations bits(keySat,0,16) : dump,long_type;
|
||||||
|
|
|
@ -18,15 +18,15 @@ meta selectGroupNumber bufr_group_number();
|
||||||
transient subsetNumber=0;
|
transient subsetNumber=0;
|
||||||
if (compressedData) {
|
if (compressedData) {
|
||||||
meta numericValues bufr_data_array(offsetSection4,offsetBeforeData,offsetEndSection4,section4Length,
|
meta numericValues bufr_data_array(offsetSection4,offsetBeforeData,offsetEndSection4,section4Length,
|
||||||
numberOfDataSubsets,subsetNumber,expandedCodes,expandedFlags,
|
numberOfSubsets,subsetNumber,expandedCodes,expandedFlags,
|
||||||
stringValues,elementsDescriptorsIndex,compressedData) ;
|
stringValues,elementsDescriptorsIndex,compressedData) : dump;
|
||||||
} else {
|
} else {
|
||||||
meta numericValues bufr_data_array(offsetSection4,offsetBeforeData,offsetEndSection4,section4Length,
|
meta numericValues bufr_data_array(offsetSection4,offsetBeforeData,offsetEndSection4,section4Length,
|
||||||
numberOfDataSubsets,subsetNumber,expandedCodes,expandedFlags,
|
numberOfSubsets,subsetNumber,expandedCodes,expandedFlags,
|
||||||
stringValues,elementsDescriptorsIndex,compressedData) ;
|
stringValues,elementsDescriptorsIndex,compressedData) : dump;
|
||||||
}
|
}
|
||||||
|
|
||||||
meta unpack unpack_bufr_values(numericValues);
|
meta unpack unpack_bufr_values(numericValues) ;
|
||||||
|
|
||||||
section_padding section4Padding;
|
section_padding section4Padding;
|
||||||
position offsetEndSection4;
|
position offsetEndSection4;
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
MEMBERS = const char* offsetBeforeDataName
|
MEMBERS = const char* offsetBeforeDataName
|
||||||
MEMBERS = const char* offsetEndSection4Name
|
MEMBERS = const char* offsetEndSection4Name
|
||||||
MEMBERS = const char* section4LengthName
|
MEMBERS = const char* section4LengthName
|
||||||
MEMBERS = const char* numberOfDataSubsetsName
|
MEMBERS = const char* numberOfSubsetsName
|
||||||
MEMBERS = const char* subsetNumberName
|
MEMBERS = const char* subsetNumberName
|
||||||
MEMBERS = const char* expandedDescriptorsName
|
MEMBERS = const char* expandedDescriptorsName
|
||||||
MEMBERS = const char* flagsName
|
MEMBERS = const char* flagsName
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
MEMBERS = grib_accessor* expandedAccessor
|
MEMBERS = grib_accessor* expandedAccessor
|
||||||
MEMBERS = int* canBeMissing
|
MEMBERS = int* canBeMissing
|
||||||
MEMBERS = long subsetNumber
|
MEMBERS = long subsetNumber
|
||||||
MEMBERS = long numberOfDataSubsets
|
MEMBERS = long numberOfSubsets
|
||||||
MEMBERS = long compressedData
|
MEMBERS = long compressedData
|
||||||
MEMBERS = grib_vdarray* numericValues
|
MEMBERS = grib_vdarray* numericValues
|
||||||
MEMBERS = grib_vsarray* stringValues
|
MEMBERS = grib_vsarray* stringValues
|
||||||
|
@ -90,7 +90,7 @@ typedef struct grib_accessor_bufr_data_array {
|
||||||
const char* offsetBeforeDataName;
|
const char* offsetBeforeDataName;
|
||||||
const char* offsetEndSection4Name;
|
const char* offsetEndSection4Name;
|
||||||
const char* section4LengthName;
|
const char* section4LengthName;
|
||||||
const char* numberOfDataSubsetsName;
|
const char* numberOfSubsetsName;
|
||||||
const char* subsetNumberName;
|
const char* subsetNumberName;
|
||||||
const char* expandedDescriptorsName;
|
const char* expandedDescriptorsName;
|
||||||
const char* flagsName;
|
const char* flagsName;
|
||||||
|
@ -102,7 +102,7 @@ typedef struct grib_accessor_bufr_data_array {
|
||||||
grib_accessor* expandedAccessor;
|
grib_accessor* expandedAccessor;
|
||||||
int* canBeMissing;
|
int* canBeMissing;
|
||||||
long subsetNumber;
|
long subsetNumber;
|
||||||
long numberOfDataSubsets;
|
long numberOfSubsets;
|
||||||
long compressedData;
|
long compressedData;
|
||||||
grib_vdarray* numericValues;
|
grib_vdarray* numericValues;
|
||||||
grib_vsarray* stringValues;
|
grib_vsarray* stringValues;
|
||||||
|
@ -227,7 +227,7 @@ static void init(grib_accessor* a,const long v, grib_arguments* params)
|
||||||
self->offsetBeforeDataName = grib_arguments_get_name(a->parent->h,params,n++);
|
self->offsetBeforeDataName = grib_arguments_get_name(a->parent->h,params,n++);
|
||||||
self->offsetEndSection4Name = grib_arguments_get_name(a->parent->h,params,n++);
|
self->offsetEndSection4Name = grib_arguments_get_name(a->parent->h,params,n++);
|
||||||
self->section4LengthName = grib_arguments_get_name(a->parent->h,params,n++);
|
self->section4LengthName = grib_arguments_get_name(a->parent->h,params,n++);
|
||||||
self->numberOfDataSubsetsName = grib_arguments_get_name(a->parent->h,params,n++);
|
self->numberOfSubsetsName = grib_arguments_get_name(a->parent->h,params,n++);
|
||||||
self->subsetNumberName = grib_arguments_get_name(a->parent->h,params,n++);
|
self->subsetNumberName = grib_arguments_get_name(a->parent->h,params,n++);
|
||||||
self->expandedDescriptorsName = grib_arguments_get_name(a->parent->h,params,n++);
|
self->expandedDescriptorsName = grib_arguments_get_name(a->parent->h,params,n++);
|
||||||
self->flagsName = grib_arguments_get_name(a->parent->h,params,n++);
|
self->flagsName = grib_arguments_get_name(a->parent->h,params,n++);
|
||||||
|
@ -315,7 +315,7 @@ static int get_descriptors(grib_accessor* a) {
|
||||||
for (i=0;i<numberOfDescriptors;i++)
|
for (i=0;i<numberOfDescriptors;i++)
|
||||||
self->canBeMissing[i]=can_be_missing(self->expanded->v[i]->code);
|
self->canBeMissing[i]=can_be_missing(self->expanded->v[i]->code);
|
||||||
|
|
||||||
ret=grib_get_long(h,self->numberOfDataSubsetsName,&(self->numberOfDataSubsets));
|
ret=grib_get_long(h,self->numberOfSubsetsName,&(self->numberOfSubsets));
|
||||||
ret=grib_get_long(h,self->compressedDataName,&(self->compressedData));
|
ret=grib_get_long(h,self->compressedDataName,&(self->compressedData));
|
||||||
ret=grib_get_long(h,self->subsetNumberName,&(self->subsetNumber));
|
ret=grib_get_long(h,self->subsetNumberName,&(self->subsetNumber));
|
||||||
|
|
||||||
|
@ -339,7 +339,7 @@ static grib_sarray* decode_string_array(grib_context* c,unsigned char* data,long
|
||||||
ret=grib_sarray_new(c,10,10);
|
ret=grib_sarray_new(c,10,10);
|
||||||
if (width) {
|
if (width) {
|
||||||
grib_context_free(c,sval);
|
grib_context_free(c,sval);
|
||||||
for (j=0;j<self->numberOfDataSubsets;j++) {
|
for (j=0;j<self->numberOfSubsets;j++) {
|
||||||
sval=(char*)grib_context_malloc_clear(c,width+1);
|
sval=(char*)grib_context_malloc_clear(c,width+1);
|
||||||
grib_decode_string(data,pos,width,sval);
|
grib_decode_string(data,pos,width,sval);
|
||||||
grib_sarray_push(c,ret,sval);
|
grib_sarray_push(c,ret,sval);
|
||||||
|
@ -368,7 +368,7 @@ static grib_darray* decode_double_array(grib_context* c,unsigned char* data,long
|
||||||
localWidth=grib_decode_unsigned_long(data,pos,6);
|
localWidth=grib_decode_unsigned_long(data,pos,6);
|
||||||
ret=grib_darray_new(c,100,100);
|
ret=grib_darray_new(c,100,100);
|
||||||
if (localWidth) {
|
if (localWidth) {
|
||||||
for (j=0;j<self->numberOfDataSubsets;j++) {
|
for (j=0;j<self->numberOfSubsets;j++) {
|
||||||
lval=grib_decode_unsigned_long(data,pos,localWidth);
|
lval=grib_decode_unsigned_long(data,pos,localWidth);
|
||||||
if (grib_is_all_bits_one(lval,localWidth) && self->canBeMissing[i]) {
|
if (grib_is_all_bits_one(lval,localWidth) && self->canBeMissing[i]) {
|
||||||
dval=GRIB_MISSING_DOUBLE;
|
dval=GRIB_MISSING_DOUBLE;
|
||||||
|
@ -436,12 +436,11 @@ static void decode_element(grib_context* c,grib_accessor_bufr_data_array* self,
|
||||||
sar=decode_string_array(c,data,pos,i,self);
|
sar=decode_string_array(c,data,pos,i,self);
|
||||||
grib_vsarray_push(c,self->stringValues,sar);
|
grib_vsarray_push(c,self->stringValues,sar);
|
||||||
index=grib_vsarray_used_size(self->stringValues);
|
index=grib_vsarray_used_size(self->stringValues);
|
||||||
dar=grib_darray_new(c,self->numberOfDataSubsets,10);
|
dar=grib_darray_new(c,self->numberOfSubsets,10);
|
||||||
sar_size=grib_sarray_used_size(sar);
|
sar_size=grib_sarray_used_size(sar);
|
||||||
index=self->numberOfDataSubsets*(index-1);
|
index=self->numberOfSubsets*(index-1);
|
||||||
for (ii=1;ii<=self->numberOfDataSubsets;ii++) {
|
for (ii=1;ii<=self->numberOfSubsets;ii++) {
|
||||||
x=(index+ii)*1000+self->expanded->v[i]->width/8;
|
x=(index+ii)*1000+self->expanded->v[i]->width/8;
|
||||||
/* x=index*1000+strlen(sar->v[idx]); */
|
|
||||||
grib_darray_push(c,dar,x);
|
grib_darray_push(c,dar,x);
|
||||||
}
|
}
|
||||||
grib_vdarray_push(c,self->numericValues,dar);
|
grib_vdarray_push(c,self->numericValues,dar);
|
||||||
|
@ -568,9 +567,10 @@ static void push_zero_element(grib_accessor_bufr_data_array* self,grib_darray* d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
static grib_accessor* create_accessor_from_descriptor(grib_accessor* a,long ide,long subset) {
|
static grib_accessor* create_accessor_from_descriptor(grib_accessor* a,long ide,long subset) {
|
||||||
grib_accessor_bufr_data_array *self =(grib_accessor_bufr_data_array*)a;
|
grib_accessor_bufr_data_array *self =(grib_accessor_bufr_data_array*)a;
|
||||||
|
int idx=0;
|
||||||
|
grib_section* section=0;
|
||||||
grib_accessor* elementAccessor=NULL;
|
grib_accessor* elementAccessor=NULL;
|
||||||
grib_action creator = {0, };
|
grib_action creator = {0, };
|
||||||
creator.op = "bufr_data_element";
|
creator.op = "bufr_data_element";
|
||||||
|
@ -578,13 +578,22 @@ static grib_accessor* create_accessor_from_descriptor(grib_accessor* a,long ide,
|
||||||
creator.flags = GRIB_ACCESSOR_FLAG_DUMP;
|
creator.flags = GRIB_ACCESSOR_FLAG_DUMP;
|
||||||
creator.set = 0;
|
creator.set = 0;
|
||||||
|
|
||||||
creator.name=self->expanded->v[self->elementsDescriptorsIndex->v[ide]]->name;
|
idx = self->compressedData ? self->elementsDescriptorsIndex->v[0]->v[ide] :
|
||||||
elementAccessor = grib_accessor_factory(section, &creator, 0, NULL);
|
self->elementsDescriptorsIndex->v[ide]->v[subset];
|
||||||
accessor_bufr_data_element_set_index(elementAccessor,ide);
|
|
||||||
accessor_bufr_data_element_set_descriptors(elementAccessor,self->expanded);
|
creator.name=self->expanded->v[idx]->shortName;
|
||||||
accessor_bufr_data_element_set_numericValues(elementAccessor,self->numericValues);
|
if (creator.name) {
|
||||||
accessor_bufr_data_element_set_stringValue(elementAccessor,self->stringValue);
|
section=a->sub_section;
|
||||||
accessor_bufr_data_element_set_compressedData(elementAccessor,self->compressedData);
|
elementAccessor = grib_accessor_factory(section, &creator, 0, NULL);
|
||||||
|
accessor_bufr_data_element_set_index(elementAccessor,ide);
|
||||||
|
accessor_bufr_data_element_set_descriptors(elementAccessor,self->expanded);
|
||||||
|
accessor_bufr_data_element_set_numericValues(elementAccessor,self->numericValues);
|
||||||
|
accessor_bufr_data_element_set_stringValues(elementAccessor,self->stringValues);
|
||||||
|
accessor_bufr_data_element_set_compressedData(elementAccessor,self->compressedData);
|
||||||
|
accessor_bufr_data_element_set_type(elementAccessor,self->expanded->v[idx]->type);
|
||||||
|
accessor_bufr_data_element_set_numberOfSubsets(elementAccessor,self->numberOfSubsets);
|
||||||
|
accessor_bufr_data_element_set_subsetNumber(elementAccessor,subset);
|
||||||
|
}
|
||||||
|
|
||||||
return elementAccessor;
|
return elementAccessor;
|
||||||
}
|
}
|
||||||
|
@ -592,23 +601,23 @@ static grib_accessor* create_accessor_from_descriptor(grib_accessor* a,long ide,
|
||||||
static int create_keys(grib_accessor* a) {
|
static int create_keys(grib_accessor* a) {
|
||||||
grib_accessor_bufr_data_array *self =(grib_accessor_bufr_data_array*)a;
|
grib_accessor_bufr_data_array *self =(grib_accessor_bufr_data_array*)a;
|
||||||
int err=0;
|
int err=0;
|
||||||
|
grib_accessor* elementAccessor=0;
|
||||||
long iss,end,elementsInSubset,ide;
|
long iss,end,elementsInSubset,ide;
|
||||||
grib_context* c=a->parent->h->context;
|
grib_section* section=a->sub_section;
|
||||||
|
|
||||||
end= self->compressedData ? 1 : self->numberOfDataSubsets;
|
end= self->compressedData ? 1 : self->numberOfSubsets;
|
||||||
|
|
||||||
for (iss=0;iss<end;iss++) {
|
for (iss=0;iss<end;iss++) {
|
||||||
elementsInSubset= self->compressedData ? grib_viarray_used_size(self->elementsDescriptorsIndex) :
|
elementsInSubset= self->compressedData ? grib_iarray_used_size(self->elementsDescriptorsIndex->v[0]) :
|
||||||
grib_iarray_used_size(self->elementsDescriptorsIndex->v[iss]);
|
grib_iarray_used_size(self->elementsDescriptorsIndex->v[iss]);
|
||||||
for (ide=0;ide<elementsInSubset;ide++) {
|
for (ide=0;ide<elementsInSubset;ide++) {
|
||||||
elementAccessor=create_accessor_from_descriptor(a,ide);
|
elementAccessor=create_accessor_from_descriptor(a,ide,iss);
|
||||||
grib_push_accessor(elementAccessor,a->subsection->block);
|
if (elementAccessor) grib_push_accessor(elementAccessor,section->block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
#define MAX_NESTED_REPLICATIONS 8
|
#define MAX_NESTED_REPLICATIONS 8
|
||||||
|
|
||||||
|
@ -662,7 +671,7 @@ static int decode_elements(grib_accessor* a) {
|
||||||
if (self->elementsDescriptorsIndex) grib_viarray_delete(c,self->elementsDescriptorsIndex);
|
if (self->elementsDescriptorsIndex) grib_viarray_delete(c,self->elementsDescriptorsIndex);
|
||||||
self->elementsDescriptorsIndex=grib_viarray_new(c,100,100);
|
self->elementsDescriptorsIndex=grib_viarray_new(c,100,100);
|
||||||
|
|
||||||
end= self->compressedData ? 1 : self->numberOfDataSubsets;
|
end= self->compressedData ? 1 : self->numberOfSubsets;
|
||||||
|
|
||||||
numberOfDescriptors=grib_bufr_descriptors_array_used_size(self->expanded);
|
numberOfDescriptors=grib_bufr_descriptors_array_used_size(self->expanded);
|
||||||
|
|
||||||
|
@ -837,7 +846,7 @@ static int decode_elements(grib_accessor* a) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* err=create_keys(a); */
|
err=create_keys(a);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -863,9 +872,9 @@ static int value_count(grib_accessor* a,long* count)
|
||||||
|
|
||||||
err=grib_get_long(a->parent->h,self->subsetNumberName,&subsetNumber);
|
err=grib_get_long(a->parent->h,self->subsetNumberName,&subsetNumber);
|
||||||
if (err) return err;
|
if (err) return err;
|
||||||
if (subsetNumber>self->numberOfDataSubsets) {
|
if (subsetNumber>self->numberOfSubsets) {
|
||||||
err=GRIB_INVALID_KEY_VALUE;
|
err=GRIB_INVALID_KEY_VALUE;
|
||||||
grib_context_log(c,GRIB_LOG_ERROR,"%s=%ld is too big, %s=%ld",self->subsetNumberName,self->numberOfDataSubsetsName);
|
grib_context_log(c,GRIB_LOG_ERROR,"%s=%ld is too big, %s=%ld",self->subsetNumberName,self->numberOfSubsetsName);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -874,14 +883,14 @@ static int value_count(grib_accessor* a,long* count)
|
||||||
|
|
||||||
*count=l;
|
*count=l;
|
||||||
if (subsetNumber<=0) {
|
if (subsetNumber<=0) {
|
||||||
*count *= self->numberOfDataSubsets;
|
*count *= self->numberOfSubsets;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (subsetNumber>0) {
|
if (subsetNumber>0) {
|
||||||
*count=grib_iarray_used_size(self->elementsDescriptorsIndex->v[subsetNumber-1]);
|
*count=grib_iarray_used_size(self->elementsDescriptorsIndex->v[subsetNumber-1]);
|
||||||
} else {
|
} else {
|
||||||
*count=0;
|
*count=0;
|
||||||
for (i=0;i<self->numberOfDataSubsets;i++)
|
for (i=0;i<self->numberOfSubsets;i++)
|
||||||
*count+=grib_iarray_used_size(self->elementsDescriptorsIndex->v[i]);
|
*count+=grib_iarray_used_size(self->elementsDescriptorsIndex->v[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -904,11 +913,11 @@ static int unpack_double(grib_accessor* a, double* val, size_t *len) {
|
||||||
l=grib_vdarray_used_size(self->numericValues);
|
l=grib_vdarray_used_size(self->numericValues);
|
||||||
err=grib_get_long(a->parent->h,self->subsetNumberName,&n);
|
err=grib_get_long(a->parent->h,self->subsetNumberName,&n);
|
||||||
if (err) return err;
|
if (err) return err;
|
||||||
err=grib_get_long(a->parent->h,self->numberOfDataSubsetsName,&numberOfSubsets);
|
err=grib_get_long(a->parent->h,self->numberOfSubsetsName,&numberOfSubsets);
|
||||||
if (err) return err;
|
if (err) return err;
|
||||||
if (n>numberOfSubsets) {
|
if (n>numberOfSubsets) {
|
||||||
err=GRIB_INVALID_KEY_VALUE;
|
err=GRIB_INVALID_KEY_VALUE;
|
||||||
grib_context_log(c,GRIB_LOG_ERROR,"%s=%ld is too big, %s=%ld",self->subsetNumberName,self->numberOfDataSubsetsName);
|
grib_context_log(c,GRIB_LOG_ERROR,"%s=%ld is too big, %s=%ld",self->subsetNumberName,self->numberOfSubsetsName);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
MEMBERS = long index
|
MEMBERS = long index
|
||||||
MEMBERS = int type
|
MEMBERS = int type
|
||||||
MEMBERS = long compressedData
|
MEMBERS = long compressedData
|
||||||
|
MEMBERS = long subsetNumber
|
||||||
|
MEMBERS = long numberOfSubsets
|
||||||
MEMBERS = bufr_descriptors_array* descriptors
|
MEMBERS = bufr_descriptors_array* descriptors
|
||||||
MEMBERS = grib_vdarray* numericValues
|
MEMBERS = grib_vdarray* numericValues
|
||||||
MEMBERS = grib_vsarray* stringValues
|
MEMBERS = grib_vsarray* stringValues
|
||||||
|
@ -63,6 +65,8 @@ typedef struct grib_accessor_bufr_data_element {
|
||||||
long index;
|
long index;
|
||||||
int type;
|
int type;
|
||||||
long compressedData;
|
long compressedData;
|
||||||
|
long subsetNumber;
|
||||||
|
long numberOfSubsets;
|
||||||
bufr_descriptors_array* descriptors;
|
bufr_descriptors_array* descriptors;
|
||||||
grib_vdarray* numericValues;
|
grib_vdarray* numericValues;
|
||||||
grib_vsarray* stringValues;
|
grib_vsarray* stringValues;
|
||||||
|
@ -157,6 +161,16 @@ void accessor_bufr_data_element_set_type(grib_accessor* a,int type) {
|
||||||
self->type=type;
|
self->type=type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void accessor_bufr_data_element_set_numberOfSubsets(grib_accessor* a,long numberOfSubsets) {
|
||||||
|
grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
|
||||||
|
self->numberOfSubsets=numberOfSubsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
void accessor_bufr_data_element_set_subsetNumber(grib_accessor* a,long subsetNumber) {
|
||||||
|
grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
|
||||||
|
self->subsetNumber=subsetNumber;
|
||||||
|
}
|
||||||
|
|
||||||
void accessor_bufr_data_element_set_compressedData(grib_accessor* a,int compressedData) {
|
void accessor_bufr_data_element_set_compressedData(grib_accessor* a,int compressedData) {
|
||||||
grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
|
grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
|
||||||
self->compressedData=compressedData;
|
self->compressedData=compressedData;
|
||||||
|
@ -184,9 +198,8 @@ void accessor_bufr_data_element_set_elementsDescriptorsIndex(grib_accessor* a,gr
|
||||||
|
|
||||||
static void init(grib_accessor* a, const long len, grib_arguments* params) {
|
static void init(grib_accessor* a, const long len, grib_arguments* params) {
|
||||||
|
|
||||||
/* grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a; */
|
|
||||||
a->length = 0;
|
a->length = 0;
|
||||||
/* a->flags |= GRIB_ACCESSOR_FLAG_READ_ONLY; */
|
a->flags |= GRIB_ACCESSOR_FLAG_READ_ONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump(grib_accessor* a, grib_dumper* dumper)
|
static void dump(grib_accessor* a, grib_dumper* dumper)
|
||||||
|
@ -208,29 +221,89 @@ static void dump(grib_accessor* a, grib_dumper* dumper)
|
||||||
|
|
||||||
static int unpack_string_array (grib_accessor* a, char** val, size_t *len)
|
static int unpack_string_array (grib_accessor* a, char** val, size_t *len)
|
||||||
{
|
{
|
||||||
/* grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a; */
|
grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
|
||||||
|
|
||||||
return GRIB_NOT_IMPLEMENTED;
|
int ret=0,i,idx;
|
||||||
|
long count=0;
|
||||||
|
grib_context* c=a->parent->h->context;
|
||||||
|
|
||||||
|
value_count(a,&count);
|
||||||
|
|
||||||
|
if (*len<count) return GRIB_ARRAY_TOO_SMALL;
|
||||||
|
|
||||||
|
if (self->compressedData) {
|
||||||
|
for (i=0;i<count;i++) {
|
||||||
|
idx=(int)self->numericValues->v[self->index]->v[i]/1000;
|
||||||
|
val[i]=grib_context_strdup(c,self->stringValues->v[idx]->v[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
idx=(int)self->numericValues->v[self->subsetNumber]->v[self->index]/1000;
|
||||||
|
val[0]=grib_context_strdup(c,self->stringValues->v[self->subsetNumber]->v[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int unpack_string (grib_accessor* a, char* val, size_t *len)
|
static int unpack_string (grib_accessor* a, char* val, size_t *len)
|
||||||
{
|
{
|
||||||
return GRIB_NOT_IMPLEMENTED;
|
sprintf(val,"test");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int unpack_long (grib_accessor* a, long* val, size_t *len)
|
static int unpack_long (grib_accessor* a, long* val, size_t *len)
|
||||||
{
|
{
|
||||||
return GRIB_NOT_IMPLEMENTED;
|
grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
|
||||||
|
int ret=0,i;
|
||||||
|
long count=0;
|
||||||
|
|
||||||
|
value_count(a,&count);
|
||||||
|
|
||||||
|
if (*len<count) return GRIB_ARRAY_TOO_SMALL;
|
||||||
|
|
||||||
|
if (self->compressedData) {
|
||||||
|
for (i=0;i<count;i++) {
|
||||||
|
val[i]=(long)self->numericValues->v[self->index]->v[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val[0]=(long)self->numericValues->v[self->subsetNumber]->v[self->index];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int unpack_double (grib_accessor* a, double* val, size_t *len)
|
static int unpack_double (grib_accessor* a, double* val, size_t *len)
|
||||||
{
|
{
|
||||||
return GRIB_NOT_IMPLEMENTED;
|
grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
|
||||||
|
int ret=0,i;
|
||||||
|
long count=0;
|
||||||
|
|
||||||
|
value_count(a,&count);
|
||||||
|
|
||||||
|
if (*len<count) return GRIB_ARRAY_TOO_SMALL;
|
||||||
|
|
||||||
|
if (self->compressedData) {
|
||||||
|
for (i=0;i<count;i++) {
|
||||||
|
val[i]=self->numericValues->v[self->index]->v[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val[0]=self->numericValues->v[self->subsetNumber]->v[self->index];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int value_count(grib_accessor* a,long* count)
|
static int value_count(grib_accessor* a,long* count)
|
||||||
{
|
{
|
||||||
return 0;
|
int ret,size;
|
||||||
|
grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
|
||||||
|
|
||||||
|
if (!self->compressedData) return 1;
|
||||||
|
|
||||||
|
size=grib_darray_used_size(self->numericValues->v[self->index]);
|
||||||
|
|
||||||
|
ret= size == 1 ? 1 : self->numberOfSubsets;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void destroy(grib_context* context,grib_accessor* a)
|
static void destroy(grib_context* context,grib_accessor* a)
|
||||||
|
@ -239,15 +312,27 @@ static void destroy(grib_context* context,grib_accessor* a)
|
||||||
|
|
||||||
static int get_native_type(grib_accessor* a){
|
static int get_native_type(grib_accessor* a){
|
||||||
grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
|
grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
|
||||||
|
int ret=GRIB_TYPE_DOUBLE;
|
||||||
|
|
||||||
/*
|
switch (self->type) {
|
||||||
if (self->compressedData) {
|
case BUFR_DESCRIPTOR_TYPE_STRING:
|
||||||
|
ret=GRIB_TYPE_STRING;
|
||||||
} else {
|
break;
|
||||||
|
case BUFR_DESCRIPTOR_TYPE_DOUBLE:
|
||||||
|
ret=GRIB_TYPE_DOUBLE;
|
||||||
|
break;
|
||||||
|
case BUFR_DESCRIPTOR_TYPE_LONG:
|
||||||
|
ret=GRIB_TYPE_LONG;
|
||||||
|
break;
|
||||||
|
case BUFR_DESCRIPTOR_TYPE_TABLE:
|
||||||
|
ret=GRIB_TYPE_LONG;
|
||||||
|
break;
|
||||||
|
case BUFR_DESCRIPTOR_TYPE_FLAG:
|
||||||
|
ret=GRIB_TYPE_LONG;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
return self->type;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ or edit "accessor.class" and rerun ./make_class.pl
|
||||||
|
|
||||||
static int pack_double(grib_accessor*, const double* val,size_t *len);
|
static int pack_double(grib_accessor*, const double* val,size_t *len);
|
||||||
static int unpack_double(grib_accessor*, double* val,size_t *len);
|
static int unpack_double(grib_accessor*, double* val,size_t *len);
|
||||||
static int value_count(grib_accessor*, long*);
|
static int value_count(grib_accessor*,long*);
|
||||||
static void init(grib_accessor*,const long, grib_arguments* );
|
static void init(grib_accessor*,const long, grib_arguments* );
|
||||||
static void init_class(grib_accessor_class*);
|
static void init_class(grib_accessor_class*);
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ static grib_accessor_class _grib_accessor_class_data_ccsds_packing = {
|
||||||
0, /* get native type */
|
0, /* get native type */
|
||||||
0, /* get sub_section */
|
0, /* get sub_section */
|
||||||
0, /* grib_pack procedures long */
|
0, /* grib_pack procedures long */
|
||||||
0, /* grib_pack procedures long */
|
0, /* grib_pack procedures long */
|
||||||
0, /* grib_pack procedures long */
|
0, /* grib_pack procedures long */
|
||||||
0, /* grib_unpack procedures long */
|
0, /* grib_unpack procedures long */
|
||||||
&pack_double, /* grib_pack procedures double */
|
&pack_double, /* grib_pack procedures double */
|
||||||
|
@ -136,6 +136,8 @@ static void init_class(grib_accessor_class* c)
|
||||||
c->unpack_long = (*(c->super))->unpack_long;
|
c->unpack_long = (*(c->super))->unpack_long;
|
||||||
c->pack_string = (*(c->super))->pack_string;
|
c->pack_string = (*(c->super))->pack_string;
|
||||||
c->unpack_string = (*(c->super))->unpack_string;
|
c->unpack_string = (*(c->super))->unpack_string;
|
||||||
|
c->pack_string_array = (*(c->super))->pack_string_array;
|
||||||
|
c->unpack_string_array = (*(c->super))->unpack_string_array;
|
||||||
c->pack_bytes = (*(c->super))->pack_bytes;
|
c->pack_bytes = (*(c->super))->pack_bytes;
|
||||||
c->unpack_bytes = (*(c->super))->unpack_bytes;
|
c->unpack_bytes = (*(c->super))->unpack_bytes;
|
||||||
c->pack_expression = (*(c->super))->pack_expression;
|
c->pack_expression = (*(c->super))->pack_expression;
|
||||||
|
|
|
@ -145,7 +145,7 @@ typedef struct grib_accessor_bufr_compressed_data {
|
||||||
const char* offsetBeforeDataName;
|
const char* offsetBeforeDataName;
|
||||||
const char* offsetEndSection4Name;
|
const char* offsetEndSection4Name;
|
||||||
const char* section4LengthName;
|
const char* section4LengthName;
|
||||||
const char* numberOfDataSubsetsName;
|
const char* numberOfSubsetsName;
|
||||||
const char* subsetNumberName;
|
const char* subsetNumberName;
|
||||||
const char* expandedDescriptorsName;
|
const char* expandedDescriptorsName;
|
||||||
const char* elementsName;
|
const char* elementsName;
|
||||||
|
@ -169,7 +169,7 @@ typedef struct grib_accessor_bufr_compressed_data {
|
||||||
long* scale;
|
long* scale;
|
||||||
long* width;
|
long* width;
|
||||||
long numberOfElements;
|
long numberOfElements;
|
||||||
long numberOfDataSubsets;
|
long numberOfSubsets;
|
||||||
size_t numberOfDescriptors;
|
size_t numberOfDescriptors;
|
||||||
double* values;
|
double* values;
|
||||||
int* is_constant;
|
int* is_constant;
|
||||||
|
|
|
@ -169,7 +169,7 @@ double rint(double x);
|
||||||
#define GRIB_HANDLE_BIG_ECMWF_GRIB1 1
|
#define GRIB_HANDLE_BIG_ECMWF_GRIB1 1
|
||||||
|
|
||||||
#define MAX_FILE_HANDLES_WITH_MULTI 10
|
#define MAX_FILE_HANDLES_WITH_MULTI 10
|
||||||
#define ACCESSORS_ARRAY_SIZE 2100
|
#define ACCESSORS_ARRAY_SIZE 20000
|
||||||
#define MAX_NUM_CONCEPTS 2000
|
#define MAX_NUM_CONCEPTS 2000
|
||||||
#define MAX_NUM_HASH_ARRAY 2000
|
#define MAX_NUM_HASH_ARRAY 2000
|
||||||
|
|
||||||
|
|
|
@ -253,6 +253,8 @@ size_t grib_viarray_used_size(grib_viarray *v);
|
||||||
/* grib_accessor_class_bufr_data_element.c */
|
/* grib_accessor_class_bufr_data_element.c */
|
||||||
void accessor_bufr_data_element_set_index(grib_accessor *a, long index);
|
void accessor_bufr_data_element_set_index(grib_accessor *a, long index);
|
||||||
void accessor_bufr_data_element_set_type(grib_accessor *a, int type);
|
void accessor_bufr_data_element_set_type(grib_accessor *a, int type);
|
||||||
|
void accessor_bufr_data_element_set_numberOfSubsets(grib_accessor *a, long numberOfSubsets);
|
||||||
|
void accessor_bufr_data_element_set_subsetNumber(grib_accessor *a, long subsetNumber);
|
||||||
void accessor_bufr_data_element_set_compressedData(grib_accessor *a, int compressedData);
|
void accessor_bufr_data_element_set_compressedData(grib_accessor *a, int compressedData);
|
||||||
void accessor_bufr_data_element_set_descriptors(grib_accessor *a, bufr_descriptors_array *descriptors);
|
void accessor_bufr_data_element_set_descriptors(grib_accessor *a, bufr_descriptors_array *descriptors);
|
||||||
void accessor_bufr_data_element_set_numericValues(grib_accessor *a, grib_vdarray *numericValues);
|
void accessor_bufr_data_element_set_numericValues(grib_accessor *a, grib_vdarray *numericValues);
|
||||||
|
|
|
@ -61,9 +61,9 @@ typedef struct grib_nearest_lambert_conformal{
|
||||||
double* lons;
|
double* lons;
|
||||||
int lons_count;
|
int lons_count;
|
||||||
double* distances;
|
double* distances;
|
||||||
int* k; /* index */
|
int* k;
|
||||||
int* i; /* index into the lons array */
|
int* i;
|
||||||
int* j; /* index into the lats array */
|
int* j;
|
||||||
const char* Ni;
|
const char* Ni;
|
||||||
const char* Nj;
|
const char* Nj;
|
||||||
} grib_nearest_lambert_conformal;
|
} grib_nearest_lambert_conformal;
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
. ./include.sh
|
. ./include.sh
|
||||||
|
|
||||||
REDIRECT=/dev/null
|
REDIRECT=/dev/null
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
# virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
|
# virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
|
||||||
#
|
#
|
||||||
|
|
||||||
set -e
|
set -ex
|
||||||
|
|
||||||
. ./include.sh
|
. ./include.sh
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ ecbuild_add_library( TARGET grib_tools
|
||||||
|
|
||||||
list( APPEND grib_tools_bins
|
list( APPEND grib_tools_bins
|
||||||
grib_keys grib_histogram grib_error grib_add big2gribex
|
grib_keys grib_histogram grib_error grib_add big2gribex
|
||||||
grib_debug grib_info grib_filter grib_ls grib_dump
|
grib_debug grib_info grib_filter grib_ls grib_dump grib_merge
|
||||||
grib2ppm grib_set grib_get grib_get_data grib_copy grib_repair
|
grib2ppm grib_set grib_get grib_get_data grib_copy grib_repair
|
||||||
grib_packing grib_cmp grib_convert grib_distance grib_corruption_check
|
grib_packing grib_cmp grib_convert grib_distance grib_corruption_check
|
||||||
grib_compare parser grib_count grib_index_build
|
grib_compare parser grib_count grib_index_build
|
||||||
|
|
|
@ -14,7 +14,7 @@ libgrib_tools_la_SOURCES = grib_tools.c \
|
||||||
dist_bin_SCRIPTS = bufr_compare_dir
|
dist_bin_SCRIPTS = bufr_compare_dir
|
||||||
|
|
||||||
bin_PROGRAMS = grib_keys grib_histogram grib_error grib_add big2gribex \
|
bin_PROGRAMS = grib_keys grib_histogram grib_error grib_add big2gribex \
|
||||||
grib_debug grib_info grib_filter grib_ls grib_dump \
|
grib_debug grib_info grib_filter grib_ls grib_dump grib_merge \
|
||||||
grib2ppm grib_set grib_get grib_get_data grib_copy grib_repair \
|
grib2ppm grib_set grib_get grib_get_data grib_copy grib_repair \
|
||||||
grib_packing grib_cmp grib_convert grib_distance grib_corruption_check\
|
grib_packing grib_cmp grib_convert grib_distance grib_corruption_check\
|
||||||
grib_compare grib_list_keys parser grib_count grib_index_build grib1to2 \
|
grib_compare grib_list_keys parser grib_count grib_index_build grib1to2 \
|
||||||
|
@ -32,6 +32,7 @@ noinst_PROGRAMS = gaussian grib_diff mars_request xref all_keys #compile #dumpl
|
||||||
|
|
||||||
grib_corruption_check_SOURCES = grib_corruption_check.c
|
grib_corruption_check_SOURCES = grib_corruption_check.c
|
||||||
grib_moments_SOURCES = grib_moments.c
|
grib_moments_SOURCES = grib_moments.c
|
||||||
|
grib_merge_SOURCES = grib_merge.c
|
||||||
grib_to_netcdf_SOURCES = grib_to_netcdf.c
|
grib_to_netcdf_SOURCES = grib_to_netcdf.c
|
||||||
grib_to_json_SOURCES = grib_to_json.c
|
grib_to_json_SOURCES = grib_to_json.c
|
||||||
grib_dump_SOURCES = grib_dump.c
|
grib_dump_SOURCES = grib_dump.c
|
||||||
|
|
|
@ -139,6 +139,7 @@ int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) {
|
||||||
grib_set_flag(h,options->print_keys[i].name,GRIB_ACCESSOR_FLAG_DUMP);
|
grib_set_flag(h,options->print_keys[i].name,GRIB_ACCESSOR_FLAG_DUMP);
|
||||||
|
|
||||||
if (json) {
|
if (json) {
|
||||||
|
grib_set_long(h,"unpack",1);
|
||||||
} else {
|
} else {
|
||||||
sprintf(tmp,"MESSAGE %d ( length=%ld )",options->handle_count,length);
|
sprintf(tmp,"MESSAGE %d ( length=%ld )",options->handle_count,length);
|
||||||
if (!grib_options_on("C"))
|
if (!grib_options_on("C"))
|
||||||
|
|
|
@ -0,0 +1,328 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2005-2012 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* C Implementation: grib_copy
|
||||||
|
*
|
||||||
|
* Author: Enrico Fucile <enrico.fucile@ecmwf.int>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "grib_tools.h"
|
||||||
|
|
||||||
|
#define MAX_KEY_VALUES 100
|
||||||
|
|
||||||
|
grib_handle *hh=0;
|
||||||
|
grib_values key_values[MAX_KEY_VALUES];
|
||||||
|
int key_values_size=MAX_KEY_VALUES;
|
||||||
|
|
||||||
|
char* grib_tool_description="Merge two fields with identical parameters and different geografical area";
|
||||||
|
char* grib_tool_name="grib_merge";
|
||||||
|
char* grib_tool_usage="[options] file file ... output_file";
|
||||||
|
|
||||||
|
grib_option grib_options[]={
|
||||||
|
/* {id, args, help}, on, command_line, value */
|
||||||
|
{"f",0,0,0,1,0},
|
||||||
|
{"c",0,0,1,0,0},
|
||||||
|
{"r",0,0,0,1,0},
|
||||||
|
{"q",0,0,1,0,0},
|
||||||
|
{"p:",0,0,1,1,0},
|
||||||
|
{"P:",0,0,0,1,0},
|
||||||
|
{"B:",0,0,1,1,"md5Product"},
|
||||||
|
{"V",0,0,0,1,0},
|
||||||
|
{"W:",0,0,0,1,0},
|
||||||
|
{"M",0,0,0,1,0},
|
||||||
|
{"U",0,0,1,0,0},
|
||||||
|
{"H",0,0,1,0,0},
|
||||||
|
{"T:",0,0,1,0,"G"},
|
||||||
|
{"S",0,0,1,0,0},
|
||||||
|
{"g",0,0,0,1,0},
|
||||||
|
{"G",0,0,0,1,0},
|
||||||
|
{"7",0,0,0,1,0},
|
||||||
|
{"v",0,0,0,1,0}
|
||||||
|
};
|
||||||
|
|
||||||
|
int grib_options_count=sizeof(grib_options)/sizeof(grib_option);
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int ret=grib_tool(argc,argv);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int grib_tool_before_getopt(grib_runtime_options* options) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int grib_tool_init(grib_runtime_options* options) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int grib_tool_new_filename_action(grib_runtime_options* options,const char* file) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int idx(double lat,double lon,double latFirst,double lonFirst,double latLast,double lonLast,
|
||||||
|
long Ni,double di,double dj) {
|
||||||
|
long ilon,ilat;
|
||||||
|
if ((ilon=(lon-lonFirst)/di) < 0 ) return -1;
|
||||||
|
if ((ilat=(latFirst-lat)/dj) < 0 ) return -1;
|
||||||
|
if (lon>lonLast) {
|
||||||
|
if (lonLast==180) {
|
||||||
|
lon-=360;
|
||||||
|
ilon=(lon-lonFirst)/di;
|
||||||
|
} else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (lat<latLast) return -1;
|
||||||
|
if ((ilat=(latFirst-lat)/dj) < 0 ) return -1;
|
||||||
|
return ilon+ilat*Ni;
|
||||||
|
}
|
||||||
|
|
||||||
|
grib_handle* merge(grib_handle* h1,grib_handle* h2) {
|
||||||
|
char s1[100]={0,};
|
||||||
|
size_t len1;
|
||||||
|
char s2[100]={0,};
|
||||||
|
size_t len2;
|
||||||
|
size_t sn;
|
||||||
|
long l1,l2;
|
||||||
|
double di,dj,di1,dj1,di2,dj2;
|
||||||
|
long bitmapPresent;
|
||||||
|
long n=0,n1,n2;
|
||||||
|
double latFirst1,latFirst2,latFirst;
|
||||||
|
double latLast1,latLast2,latLast;
|
||||||
|
double lonFirst1,lonFirst2,lonFirst;
|
||||||
|
double lonLast1,lonLast2,lonLast;
|
||||||
|
double missingValue;
|
||||||
|
double *v=0,*v1=0,*v2=0,*lat1=0,*lat2=0,*lon1=0,*lon2=0,*lat=0,*lon=0;
|
||||||
|
long i,j,iscan,jscan,Ni,Nj,idj,idi;
|
||||||
|
long Ni1,Nj1,Ni2,Nj2;
|
||||||
|
grib_handle* h=NULL;
|
||||||
|
grib_context* c;
|
||||||
|
int err=0;
|
||||||
|
/*
|
||||||
|
int dump_flags= GRIB_DUMP_FLAG_CODED
|
||||||
|
| GRIB_DUMP_FLAG_OCTECT
|
||||||
|
| GRIB_DUMP_FLAG_VALUES
|
||||||
|
| GRIB_DUMP_FLAG_READ_ONLY;
|
||||||
|
|
||||||
|
*/
|
||||||
|
c=grib_context_get_default();
|
||||||
|
/* same products? */
|
||||||
|
if (grib_key_equal(h1,h2,"md5Product",GRIB_TYPE_STRING,&err)==0 && err==0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* can we do it?*/
|
||||||
|
|
||||||
|
len2=sizeof(s2)/sizeof(*s2);
|
||||||
|
err=grib_get_string(h2,"gridType",s2,&len2);
|
||||||
|
if (strcmp(s2,"regular_ll")) {
|
||||||
|
grib_context_log(h1->context,GRIB_LOG_WARNING,"gridType=%s not supported",s2);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
len1=sizeof(s1)/sizeof(*s1);
|
||||||
|
err=grib_get_string(h1,"gridType",s1,&len1);
|
||||||
|
if (strcmp(s1,"regular_ll")) {
|
||||||
|
grib_context_log(h1->context,GRIB_LOG_WARNING,"gridType=%s not supported",s1);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!grib_key_equal(h1,h2,"iDirectionIncrementInDegrees",GRIB_TYPE_DOUBLE,&err) ) {
|
||||||
|
grib_context_log(h1->context,GRIB_LOG_WARNING,
|
||||||
|
"unable to merge: different iDirectionIncrementInDegrees");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!grib_key_equal(h1,h2,"jDirectionIncrementInDegrees",GRIB_TYPE_DOUBLE,&err) ) {
|
||||||
|
grib_context_log(h1->context,GRIB_LOG_WARNING,
|
||||||
|
"unable to merge: different jDirectionIncrementInDegrees");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
grib_get_long(h1,"latitudeOfFirstGridPoint",&l1);
|
||||||
|
grib_get_long(h2,"latitudeOfFirstGridPoint",&l2);
|
||||||
|
grib_get_long(h2,"jDirectionIncrement",&idj);
|
||||||
|
if ( (l1-l2) % idj ) {
|
||||||
|
grib_context_log(h1->context,GRIB_LOG_WARNING, "unable to merge: incompatible grid");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
grib_get_long(h1,"longitudeOfFirstGridPoint",&l1);
|
||||||
|
grib_get_long(h2,"longitudeOfFirstGridPoint",&l2);
|
||||||
|
grib_get_long(h2,"iDirectionIncrement",&idi);
|
||||||
|
if ( (l1-l2) % idi ) {
|
||||||
|
grib_context_log(h1->context,GRIB_LOG_WARNING, "unable to merge: incompatible grid");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* yes we can!*/
|
||||||
|
|
||||||
|
/* do we have something to do?*/
|
||||||
|
|
||||||
|
if ( grib_key_equal(h1,h2,"latitudeOfFirstGridPointInDegrees",GRIB_TYPE_DOUBLE,&err) &&
|
||||||
|
grib_key_equal(h1,h2,"latitudeOfLastGridPointInDegrees",GRIB_TYPE_DOUBLE,&err) &&
|
||||||
|
grib_key_equal(h1,h2,"longitudeOfFirstGridPointInDegrees",GRIB_TYPE_DOUBLE,&err) &&
|
||||||
|
grib_key_equal(h1,h2,"longitudeOfLastGridPointInDegrees",GRIB_TYPE_DOUBLE,&err)
|
||||||
|
) {
|
||||||
|
/* no we don't */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* yes we do! */
|
||||||
|
|
||||||
|
/* check scanning mode */
|
||||||
|
grib_get_long(h1,"iScansNegatively",&iscan);
|
||||||
|
if (iscan) grib_set_long(h1,"swapScanningLon",1);
|
||||||
|
grib_get_long(h2,"iScansNegatively",&iscan);
|
||||||
|
if (iscan) grib_set_long(h2,"swapScanningLon",1);
|
||||||
|
|
||||||
|
grib_get_long(h1,"jScansPositively",&jscan);
|
||||||
|
if (jscan) grib_set_long(h1,"swapScanningLat",1);
|
||||||
|
grib_get_long(h2,"jScansPositively",&jscan);
|
||||||
|
if (jscan) grib_set_long(h2,"swapScanningLat",1);
|
||||||
|
|
||||||
|
grib_get_double(h1,"latitudeOfFirstGridPointInDegrees",&latFirst1);
|
||||||
|
grib_get_double(h2,"latitudeOfFirstGridPointInDegrees",&latFirst2);
|
||||||
|
grib_get_double(h1,"longitudeOfFirstGridPointInDegrees",&lonFirst1);
|
||||||
|
grib_get_double(h2,"longitudeOfFirstGridPointInDegrees",&lonFirst2);
|
||||||
|
|
||||||
|
latFirst = latFirst1>latFirst2 ? latFirst1 : latFirst2;
|
||||||
|
lonFirst = lonFirst1<lonFirst2 ? lonFirst1 : lonFirst2;
|
||||||
|
|
||||||
|
grib_get_double(h1,"latitudeOfLastGridPointInDegrees",&latLast1);
|
||||||
|
grib_get_double(h2,"latitudeOfLastGridPointInDegrees",&latLast2);
|
||||||
|
grib_get_double(h1,"longitudeOfLastGridPointInDegrees",&lonLast1);
|
||||||
|
grib_get_double(h2,"longitudeOfLastGridPointInDegrees",&lonLast2);
|
||||||
|
|
||||||
|
latLast = latLast1<latLast2 ? latLast1 : latLast2;
|
||||||
|
lonLast = lonLast1>lonLast2 ? lonLast1 : lonLast2;
|
||||||
|
|
||||||
|
grib_get_double(h1,"iDirectionIncrementInDegrees",&di1);
|
||||||
|
grib_get_double(h1,"jDirectionIncrementInDegrees",&dj1);
|
||||||
|
grib_get_double(h2,"iDirectionIncrementInDegrees",&di2);
|
||||||
|
grib_get_double(h2,"jDirectionIncrementInDegrees",&dj2);
|
||||||
|
grib_get_double(h1,"iDirectionIncrementInDegrees",&di);
|
||||||
|
grib_get_double(h1,"jDirectionIncrementInDegrees",&dj);
|
||||||
|
grib_get_long(h1,"Ni",&Ni1);
|
||||||
|
grib_get_long(h1,"Nj",&Nj1);
|
||||||
|
grib_get_long(h2,"Ni",&Ni2);
|
||||||
|
grib_get_long(h2,"Nj",&Nj2);
|
||||||
|
|
||||||
|
if (lonFirst==0 && lonLast==360) lonLast-=di;
|
||||||
|
if (lonFirst==-180 && lonLast==180) {
|
||||||
|
lonFirst=0;
|
||||||
|
lonLast=360-di;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create new grib for bigger area*/
|
||||||
|
h=grib_handle_clone(h1);
|
||||||
|
grib_set_double(h,"latitudeOfFirstGridPointInDegrees",latFirst);
|
||||||
|
grib_set_double(h,"longitudeOfFirstGridPointInDegrees",lonFirst);
|
||||||
|
grib_set_double(h,"latitudeOfLastGridPointInDegrees",latLast);
|
||||||
|
grib_set_double(h,"longitudeOfLastGridPointInDegrees",lonLast);
|
||||||
|
Ni=fabs(lonLast-lonFirst)/di+1;
|
||||||
|
Nj=fabs(latLast-latFirst)/dj+1;
|
||||||
|
|
||||||
|
grib_set_long(h,"Ni",Ni);
|
||||||
|
grib_set_long(h,"Nj",Nj);
|
||||||
|
|
||||||
|
grib_get_long(h,"bitmapPresent",&bitmapPresent);
|
||||||
|
if (!bitmapPresent) grib_set_long(h,"bitmapPresent",1);
|
||||||
|
|
||||||
|
grib_get_long(h,"numberOfPoints",&n);
|
||||||
|
grib_get_double(h,"missingValue",&missingValue);
|
||||||
|
v=grib_context_malloc_clear(h->context,sizeof(double)*n);
|
||||||
|
for (i=0;i<n;i++) v[i]=1.0;
|
||||||
|
sn=n;
|
||||||
|
grib_set_double_array(h,"values",v,sn);
|
||||||
|
for (i=0;i<n;i++) v[i]=missingValue;
|
||||||
|
lat=grib_context_malloc_clear(h->context,sizeof(double)*n);
|
||||||
|
lon=grib_context_malloc_clear(h->context,sizeof(double)*n);
|
||||||
|
sn=n;
|
||||||
|
grib_get_double_array(h,"latitudes",lat,&sn);
|
||||||
|
grib_get_double_array(h,"longitudes",lon,&sn);
|
||||||
|
|
||||||
|
grib_get_long(h1,"numberOfPoints",&n1);
|
||||||
|
v1=grib_context_malloc_clear(h->context,sizeof(double)*n1);
|
||||||
|
lat1=grib_context_malloc_clear(h->context,sizeof(double)*n1);
|
||||||
|
lon1=grib_context_malloc_clear(h->context,sizeof(double)*n1);
|
||||||
|
sn=n1;
|
||||||
|
grib_get_double_array(h1,"latitudes",lat1,&sn);
|
||||||
|
grib_get_double_array(h1,"longitudes",lon1,&sn);
|
||||||
|
grib_get_double_array(h1,"values",v1,&sn);
|
||||||
|
|
||||||
|
grib_get_long(h2,"numberOfPoints",&n2);
|
||||||
|
v2=grib_context_malloc_clear(h->context,sizeof(double)*n2);
|
||||||
|
lat2=grib_context_malloc_clear(h->context,sizeof(double)*n2);
|
||||||
|
lon2=grib_context_malloc_clear(h->context,sizeof(double)*n2);
|
||||||
|
sn=n2;
|
||||||
|
grib_get_double_array(h2,"latitudes",lat2,&sn);
|
||||||
|
grib_get_double_array(h2,"longitudes",lon2,&sn);
|
||||||
|
grib_get_double_array(h2,"values",v2,&sn);
|
||||||
|
|
||||||
|
for (i=0;i<n;i++) {
|
||||||
|
if ((j=idx(lat[i],lon[i],latFirst1,lonFirst1,latLast1,lonLast1,Ni1,di1,dj1)) >=0 ) {
|
||||||
|
v[i]=v1[j];
|
||||||
|
} else if ( (j=idx(lat[i],lon[i],latFirst2,lonFirst2,latLast2,lonLast2,Ni2,di2,dj2))>=0) {
|
||||||
|
v[i]=v2[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
grib_set_double_array(h,"values",v,n);
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) {
|
||||||
|
int err=0;
|
||||||
|
grib_handle* hm=0;
|
||||||
|
char md5[200]={0,};
|
||||||
|
char fname[210]={0,};
|
||||||
|
size_t lmd5;
|
||||||
|
|
||||||
|
if (!hh) { hh=grib_handle_clone(h); return 0; }
|
||||||
|
grib_get_string(h,"md5Product",md5,&lmd5);
|
||||||
|
sprintf(fname,"_%s.orig.grib",md5);
|
||||||
|
grib_write_message(h,fname,"a");
|
||||||
|
|
||||||
|
if ((hm=merge(h,hh))==NULL ) {
|
||||||
|
grib_tools_write_message(options,hh);
|
||||||
|
lmd5=sizeof(md5)/sizeof(*md5);
|
||||||
|
grib_get_string(hh,"md5Product",md5,&lmd5);
|
||||||
|
sprintf(fname,"_%s.merge.grib",md5);
|
||||||
|
grib_write_message(hh,fname,"a");
|
||||||
|
}
|
||||||
|
grib_handle_delete(hh);
|
||||||
|
hh = hm!=NULL ? hm : grib_handle_clone(h) ;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int grib_tool_skip_handle(grib_runtime_options* options, grib_handle* h) {
|
||||||
|
grib_handle_delete(h);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void grib_tool_print_key_values(grib_runtime_options* options,grib_handle* h) {
|
||||||
|
grib_print_key_values(options,h);
|
||||||
|
}
|
||||||
|
|
||||||
|
int grib_tool_finalise_action(grib_runtime_options* options) {
|
||||||
|
grib_tools_write_message(options,hh);
|
||||||
|
if (options->outfile->file) {
|
||||||
|
fclose(options->outfile->file);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue