Merge branch 'feature/grid_complex_encoding' of github.com:ecmwf/eccodes into feature/grid_complex_encoding

This commit is contained in:
Eugen Betke 2023-04-21 14:16:54 +00:00
commit 9c6ad56c01
64 changed files with 8871 additions and 8151 deletions

View File

@ -1 +1 @@
-DENABLE_EXTRA_TESTS=1
-DENABLE_EXTRA_TESTS=1 -DECCODES_INSTALL_EXTRA_TOOLS=1

19
.github/ci-nightly-test.sh vendored Normal file
View File

@ -0,0 +1,19 @@
#!/bin/bash
set -e
# We do not want to come across the ecCodes tools in the toolbox
module unload ecmwf-toolbox
module load cdo/new
module load numdiff
module load nccmp
module load netcdf4/new
module load gnuparallel/new
module load python3
cd ~masn/REGRESSION_TESTING/ecCodes
./par-suite.sh -w $TMPDIR/install/eccodes
# For debugging specific test(s)
# ./seq-suite.sh -w $TMPDIR/install/eccodes -d -t py_

View File

@ -73,3 +73,12 @@ jobs:
repository: private-downstream-ci
event_type: downstream-ci-hpc
payload: '{"eccodes": "ecmwf/eccodes@${{ github.event.pull_request.head.sha || github.sha }}"}'
codecov:
name: code-coverage
if: ${{ !github.event.pull_request.head.repo.fork && github.event.action != 'labeled' || github.event.label.name == 'approved-for-ci' }}
uses: ./.github/workflows/reusable-ci.yml
with:
eccodes: ecmwf/eccodes@${{ github.event.pull_request.head.sha || github.sha }}
codecov: true
secrets: inherit

16
.github/workflows/nightly.yml vendored Normal file
View File

@ -0,0 +1,16 @@
name: nightly
on:
workflow_dispatch: ~
# Run at 20:00 UTC every day (on default branch)
schedule:
- cron: '0 20 * * *'
jobs:
test:
uses: ./.github/workflows/reusable-ci-hpc.yml
with:
eccodes: ecmwf/eccodes@${{ github.event.pull_request.head.sha || github.sha }}
nightly_test: true
secrets: inherit

View File

@ -6,6 +6,10 @@ on:
eccodes:
required: false
type: string
nightly_test:
required: false
type: boolean
default: false
jobs:
ci-hpc:
@ -19,5 +23,11 @@ jobs:
ecbuild
ninja
aec
netcdf4/new
--parallel: 64
--cmake-options: |
-DENABLE_EXTRA_TESTS=1
${{ inputs.nightly_test && '-DENABLE_PNG=1,-DENABLE_NETCDF=1' || '' }}
${{ inputs.nightly_test && '--post-script: .github/ci-nightly-test.sh' || '' }}
${{ inputs.nightly_test && '--force-build: true' || '' }}
secrets: inherit

View File

@ -6,6 +6,10 @@ on:
eccodes:
required: false
type: string
codecov:
required: false
type: boolean
default: false
jobs:
ci:
@ -14,6 +18,7 @@ jobs:
with:
repository: ${{ inputs.eccodes || 'ecmwf/eccodes@develop' }}
name_prefix: eccodes-
codecov_upload: ${{ inputs.codecov }}
build_package_inputs: |
repository: ${{ inputs.eccodes || 'ecmwf/eccodes@develop' }}
self_coverage: true

View File

@ -21,8 +21,8 @@ cmake_minimum_required( VERSION 3.12 FATAL_ERROR )
find_package( ecbuild 3.7 REQUIRED HINTS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../ecbuild)
# Initialise project
project( eccodes VERSION 2.30.0 LANGUAGES CXX )
set(CMAKE_CXX_STANDARD 11)
project( eccodes VERSION 2.31.0 LANGUAGES CXX )
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

View File

@ -74,7 +74,7 @@
210 210 Frascati (ESA/ESRIN)
211 211 Lannion
212 212 Lisboa
213 213 Reykjavik
213 birk Reykjavik
214 lemm INM Madrid
215 lssw Zurich
216 216 Service ARGOS Toulouse

View File

@ -73,7 +73,7 @@
210 210 Frascati (ESA/ESRIN)
211 211 Lannion
212 212 Lisboa
213 213 Reykjavik
213 birk Reykjavik
214 lemm INM Madrid
215 lssw Zurich
216 216 Service ARGOS Toulouse

View File

@ -112,10 +112,6 @@ if( indicatorOfTypeOfLevel == 109 ||
{
alias mars.levelist = level;
}
if (indicatorOfTypeOfLevel == 117) {
# See ECC-1081
constant levelFactor = 6;
}
unsigned[1] yearOfCentury : edition_specific;
unsigned[1] month;

View File

@ -31,14 +31,12 @@ include "grib2/section.0.def";
template core "grib2/sections.def";
#if(!new())
#{
#lookup[4] endOfProduct(0);
#while(endOfProduct != `7777`)
#{
#template core "grib2/sections.def";
#lookup[4] endOfProduct(0);
#}
#if(!new()) {
# lookup[4] endOfProduct(0);
# while(endOfProduct != `7777`) {
# template core "grib2/sections.def";
# lookup[4] endOfProduct(0);
# }
#}
template section_8 "grib2/section.8.def";

View File

@ -1,96 +0,0 @@
# Code table 2.0: Identification of centres for local section 2
0 0 Absent
1 ammc Melbourne (WMC)
2 2 Melbourne (WMC)
4 rums Moscow (WMC)
5 5 Moscow (WMC)
7 kwbc US National Weather Service - NCEP (WMC)
8 8 US National Weather Service - NWSTG (WMC)
9 9 US National Weather Service - Other (WMC)
10 10 Cairo (RSMC/RAFC)
12 12 Dakar (RSMC/RAFC)
14 14 Nairobi (RSMC/RAFC)
16 16 Atananarivo (RSMC)
18 18 Tunis-Casablanca (RSMC)
20 20 Las Palmas (RAFC)
21 21 Algiers (RSMC)
22 22 Lagos (RSMC)
24 fapr Pretoria (RSMC)
26 26 Khabarovsk (RSMC)
28 28 New Delhi (RSMC/RAFC)
30 30 Novosibirsk (RSMC)
32 32 Tashkent (RSMC)
33 33 Jeddah (RSMC)
34 rjtd Japanese Meteorological Agency - Tokyo (RSMC)
36 36 Bankok
37 37 Ulan Bator
38 babj Beijing (RSMC)
40 rksl Seoul
41 sabm Buenos Aires (RSMC/RAFC)
43 43 Brasilia (RSMC/RAFC)
45 45 Santiago
46 sbsj Brasilian Space Agency - INPE
51 51 Miami (RSMC/RAFC)
52 52 National Hurricane Center, Miami
53 53 Canadian Meteorological Service - Montreal (RSMC)
54 cwao Canadian Meteorological Service - Montreal (RSMC)
55 55 San Francisco
57 57 U.S. Air Force - Global Weather Center
58 fnmo US Navy - Fleet Numerical Oceanography Center
59 59 NOAA Forecast Systems Lab, Boulder CO
60 60 National Center for Atmospheric Research (NCAR), Boulder, CO
64 64 Honolulu
65 65 Darwin (RSMC)
67 67 Melbourne (RSMC)
69 nzkl Wellington (RSMC/RAFC)
74 egrr U.K. Met Office - Exeter
76 76 Moscow (RSMC/RAFC)
78 edzw Offenbach (RSMC)
80 cnmc Rome (RSMC)
82 eswi Norrkoping
84 lfpw French Weather Service - Toulouse
85 lfpw French Weather Service - Toulouse
86 86 Helsinki
87 87 Belgrade
88 enmi Oslo
89 89 Prague
90 90 Episkopi
91 91 Ankara
92 92 Frankfurt/Main (RAFC)
93 93 London (WAFC)
94 ekmi Copenhagen
95 95 Rota
96 96 Athens
97 97 European Space Agency (ESA)
98 ecmf European Centre for Medium-Range Weather Forecasts
99 99 DeBilt, Netherlands
#100 to 109 Reserved for centres in Region I which are not in the list above
110 110 Hong-Kong
#111 to 133 Reserved for centres in Region II which are not in the list above
#134 to 153 Reserved for centres in Region I which are not listed above
#154 to 159 Reserved for centres in Region III which are not in the list above
160 160 US NOAA/NESDIS
# 161 to 185 Reserved for centres in Region IV which are not in the list above
# 186 to 198 Reserved for centres in Region I which are not listed above
# 199 to 209 Reserved for centres in Region V which are not in the list above
195 wiix Indonesia (NMC)
204 204 National Institute of Water and Atmospheric Research (NIWA - New Zealand)
210 210 Frascati (ESA/ESRIN)
211 211 Lannion
212 212 Lisboa
213 213 Reykjavik
214 lemm INM
215 lssw Zurich
216 216 Service ARGOS Toulouse
218 habp Budapest
224 lowm Austria
227 ebum Belgium (NMC)
233 eidb Dublin
235 ingv INGV
239 crfc CERFAX
246 ifmk IfM-Kiel
247 hadc Hadley Centre
250 cosmo COnsortium for Small scale MOdelling (COSMO)
251 251 Meteorological Cooperation on Operational NWP (MetCoOp)
254 eums EUMETSAT Operation Centre
1098 tigge TIGGE CENTRES

View File

@ -0,0 +1,10 @@
# (C) Copyright 2005- ECMWF.
# TEMPLATE 4.65533, Individual member for large ensemble forecast, control and perturbed, at a horizontal level or in a horizontal layer at a point in time
include "grib2/template.4.parameter.def"
include "grib2/template.4.generating_process.def"
include "grib2/template.4.forecast_time.def"
include "grib2/template.4.point_in_time.def"
include "grib2/template.4.horizontal.def"
include "grib2/template.4.leps.def"

View File

@ -0,0 +1,10 @@
# (C) Copyright 2005- ECMWF.
# TEMPLATE 4.65534, Individual member for large ensemble forecast, control and perturbed, at a horizontal level or in a horizontal layer in a continuous or non-continuous time interval
include "grib2/template.4.parameter.def"
include "grib2/template.4.generating_process.def"
include "grib2/template.4.forecast_time.def"
include "grib2/template.4.horizontal.def"
include "grib2/template.4.leps.def"
include "grib2/template.4.statistical.def"

View File

@ -51,7 +51,12 @@ if (section2Used == 1) {
}
}
transient genVertHeightCoords = 0;
template productDefinition "grib2/template.4.[productDefinitionTemplateNumber:l].def" ;
if (productDefinitionTemplateNumber >= 32768) {
template productDefinition "grib2/local/[centreForLocal]/template.4.[productDefinitionTemplateNumber:l].def";
} else {
template productDefinition "grib2/template.4.[productDefinitionTemplateNumber:l].def";
}
if (defined(marsStream) && defined(marsType)) {
template_nofail marsKeywords1 "mars/grib.[marsStream:s].[marsType:s].def";

View File

@ -0,0 +1,3 @@
# Code table 4.0 - Product definition template number
65533 65533 Individual member for large ensemble forecast, control and perturbed, at a horizontal level or in a horizontal layer at a point in time
65534 65534 Individual member for large ensemble forecast, control and perturbed, at a horizontal level or in a horizontal layer, in a continuous or non-continuous interval

View File

@ -0,0 +1,13 @@
# (C) Copyright 2005- ECMWF.
# Type of ensemble forecast
codetable[1] typeOfEnsembleForecast ('4.6.table',masterDir,localDir) = 255 : dump;
# Perturbation number
unsigned[4] perturbationNumber : dump;
alias number=perturbationNumber;
# Number of forecasts in ensemble
unsigned[4] numberOfForecastsInEnsemble : dump;
alias totalNumber=numberOfForecastsInEnsemble;

View File

@ -33,3 +33,8 @@ meta _TS spectral_truncation(J,K,M,TS) : read_only,hidden;
codetable[1] unpackedSubsetPrecision ('5.7.table',masterDir,localDir) = 2 : dump;
alias precisionOfTheUnpackedSubset=unpackedSubsetPrecision;
concept accuracy(zero) {
32 = { unpackedSubsetPrecision = 1; }
64 = { unpackedSubsetPrecision = 2; }
128 = { unpackedSubsetPrecision = 3; }
} : long_type, no_copy;

View File

@ -68,3 +68,11 @@
'iceLayerUnderSnowOnWater' = {typeOfFirstFixedSurface=175; typeOfSecondFixedSurface=176;}
'iceBottomOnWater' = {typeOfFirstFixedSurface=176; typeOfSecondFixedSurface=255;}
'indefiniteSoilDepth' = {typeOfFirstFixedSurface=177; typeOfSecondFixedSurface=255;}
'meltPondTop' = {typeOfFirstFixedSurface=188; typeOfSecondFixedSurface=255;}
'meltPondBottom' = {typeOfFirstFixedSurface=189; typeOfSecondFixedSurface=255;}
'entireMeltPond' = {typeOfFirstFixedSurface=188; typeOfSecondFixedSurface=189;}
'iceLayerAboveWaterSurface' = {typeOfFirstFixedSurface=174; typeOfSecondFixedSurface=160;
scaleFactorOfSecondFixedSurface=0; scaledValueOfSecondFixedSurface=0;}
'waterSurfaceToIsothermalOceanLayer' = {typeOfFirstFixedSurface=160; typeOfSecondFixedSurface=20;
scaledValueOfFirstFixedSurface=0; scaleFactorOfFirstFixedSurface=0;}

View File

@ -78,7 +78,7 @@
210 210 Frascati (ESA/ESRIN)
211 211 Lannion
212 212 Lisboa
213 213 Reykjavik
213 birk Reykjavik
214 lemm INM
215 lssw Zurich
216 216 Service ARGOS Toulouse

View File

@ -1,96 +0,0 @@
# Code table 2.0: Identification of centres for local section 2
0 0 Absent
1 ammc Melbourne (WMC)
2 2 Melbourne (WMC)
4 rums Moscow (WMC)
5 5 Moscow (WMC)
7 kwbc US National Weather Service - NCEP (WMC)
8 8 US National Weather Service - NWSTG (WMC)
9 9 US National Weather Service - Other (WMC)
10 10 Cairo (RSMC/RAFC)
12 12 Dakar (RSMC/RAFC)
14 14 Nairobi (RSMC/RAFC)
16 16 Atananarivo (RSMC)
18 18 Tunis-Casablanca (RSMC)
20 20 Las Palmas (RAFC)
21 21 Algiers (RSMC)
22 22 Lagos (RSMC)
24 fapr Pretoria (RSMC)
26 26 Khabarovsk (RSMC)
28 28 New Delhi (RSMC/RAFC)
30 30 Novosibirsk (RSMC)
32 32 Tashkent (RSMC)
33 33 Jeddah (RSMC)
34 rjtd Japanese Meteorological Agency - Tokyo (RSMC)
36 36 Bankok
37 37 Ulan Bator
38 babj Beijing (RSMC)
40 rksl Seoul
41 sabm Buenos Aires (RSMC/RAFC)
43 43 Brasilia (RSMC/RAFC)
45 45 Santiago
46 sbsj Brasilian Space Agency - INPE
51 51 Miami (RSMC/RAFC)
52 52 National Hurricane Center, Miami
53 53 Canadian Meteorological Service - Montreal (RSMC)
54 cwao Canadian Meteorological Service - Montreal (RSMC)
55 55 San Francisco
57 57 U.S. Air Force - Global Weather Center
58 fnmo US Navy - Fleet Numerical Oceanography Center
59 59 NOAA Forecast Systems Lab, Boulder CO
60 60 National Center for Atmospheric Research (NCAR), Boulder, CO
64 64 Honolulu
65 65 Darwin (RSMC)
67 67 Melbourne (RSMC)
69 nzkl Wellington (RSMC/RAFC)
74 egrr U.K. Met Office - Exeter
76 76 Moscow (RSMC/RAFC)
78 edzw Offenbach (RSMC)
80 cnmc Rome (RSMC)
82 eswi Norrkoping
84 lfpw French Weather Service - Toulouse
85 lfpw French Weather Service - Toulouse
86 86 Helsinki
87 87 Belgrade
88 enmi Oslo
89 89 Prague
90 90 Episkopi
91 91 Ankara
92 92 Frankfurt/Main (RAFC)
93 93 London (WAFC)
94 ekmi Copenhagen
95 95 Rota
96 96 Athens
97 97 European Space Agency (ESA)
98 ecmf European Centre for Medium-Range Weather Forecasts
99 99 DeBilt, Netherlands
#100 to 109 Reserved for centres in Region I which are not in the list above
110 110 Hong-Kong
#111 to 133 Reserved for centres in Region II which are not in the list above
#134 to 153 Reserved for centres in Region I which are not listed above
#154 to 159 Reserved for centres in Region III which are not in the list above
160 160 US NOAA/NESDIS
# 161 to 185 Reserved for centres in Region IV which are not in the list above
# 186 to 198 Reserved for centres in Region I which are not listed above
# 199 to 209 Reserved for centres in Region V which are not in the list above
195 wiix Indonesia (NMC)
204 204 National Institute of Water and Atmospheric Research (NIWA - New Zealand)
210 210 Frascati (ESA/ESRIN)
211 211 Lannion
212 212 Lisboa
213 213 Reykjavik
214 lemm INM
215 lssw Zurich
216 216 Service ARGOS Toulouse
218 habp Budapest
224 lowm Austria
227 ebum Belgium (NMC)
233 eidb Dublin
235 ingv INGV
239 crfc CERFAX
246 ifmk IfM-Kiel
247 hadc Hadley Centre
250 cosmo COnsortium for Small scale MOdelling (COSMO)
251 251 Meteorological Cooperation on Operational NWP (MetCoOp)
254 eums EUMETSAT Operation Centre
1098 tigge TIGGE CENTRES

View File

@ -10,6 +10,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "eccodes.h"
/* See JIRA issue GRIB-361 */
@ -23,6 +24,10 @@ int main()
codes_handle* h = NULL;
const char* filename = "bigfile.grib";
#ifndef ECCODES_ON_WINDOWS
unsigned int seed = time(NULL);
#endif
numbytes = ni * nj * sizeof(double);
values = (double*)malloc(numbytes);
if (!values) {
@ -31,7 +36,11 @@ int main()
}
for (i = 0; i < ni * nj; i++) {
double r = rand() * 1.0 / RAND_MAX;
#ifndef ECCODES_ON_WINDOWS
double r = rand_r(&seed) * 1.0 / RAND_MAX;
#else
double r = rand() * 1.0 / RAND_MAX;
#endif
values[i] = r;
}
@ -65,7 +74,6 @@ int main()
CODES_CHECK(codes_set_double_array(h, "values", values, ni * nj), 0);
codes_write_message(h, filename, "w");
/*printf("Wrote file %s\n", filename);*/
codes_handle_delete(h);
free(values);

View File

@ -9,10 +9,13 @@
. ./include.ctest.sh
# The executable should produce a GRIB1 file
# The executable will produce a GRIB1 file called "bigfile.grib"
output=bigfile.grib
${examples_dir}/c_large_grib1
# Make sure the newly created file can be listed OK
output=bigfile.grib
${tools_dir}/grib_ls $output > /dev/null
${tools_dir}/grib_ls -p numberOfDataPoints,numberOfCodedValues,numberOfMissing $output
num=$(${tools_dir}/grib_get -p numberOfDataPoints $output)
[ $num = 8294400 ]
rm -f $output

View File

@ -46,7 +46,7 @@ static void destroy (grib_context*,grib_action*);
typedef struct grib_action_concept {
grib_action act;
grib_action act;
/* Members defined in gen */
long len;
grib_arguments* params;

View File

@ -10,7 +10,6 @@
/***************************************************************************
* Jean Baptiste Filippi - 01.11.2005 *
* Enrico Fucile *
***************************************************************************/
#include "grib_api_internal.h"
@ -88,6 +87,9 @@ static void init_class(grib_action_class* c)
grib_action* grib_action_create_trigger(grib_context* context, grib_arguments* args, grib_action* block)
{
Assert(!"action_class_trigger::grib_action_create_trigger: 'trigger' statement is deprecated");
return NULL;
#if 0
char name[1024];
const size_t nameLen = sizeof(name);
@ -108,26 +110,31 @@ grib_action* grib_action_create_trigger(grib_context* context, grib_arguments* a
a->block = block;
return act;
#endif
}
static void dump(grib_action* act, FILE* f, int lvl)
{
/* grib_action_trigger* a = ( grib_action_trigger*)act; */
Assert(!"action_class_trigger::dump: 'trigger' statement is deprecated");
#if 0
int i = 0;
for (i = 0; i < lvl; i++)
grib_context_print(act->context, f, " ");
grib_context_print(act->context, f, "Trigger\n");
#endif
}
static int create_accessor(grib_section* p, grib_action* act, grib_loader* h)
{
Assert(!"action_class_trigger::create_accessor: 'trigger' statement is deprecated");
#if 0
int ret = GRIB_SUCCESS;
grib_action_trigger* a = (grib_action_trigger*)act;
grib_action* next = NULL;
grib_accessor* as = NULL;
grib_section* gs = NULL;
as = grib_accessor_factory(p, act, 0, NULL);
if (!as)
@ -147,7 +154,7 @@ static int create_accessor(grib_section* p, grib_action* act, grib_loader* h)
return ret;
next = next->next;
}
#endif
return GRIB_SUCCESS;
}
@ -160,8 +167,10 @@ static grib_action* reparse(grib_action* a, grib_accessor* acc, int* doit)
/* COMEBACK */
static void destroy(grib_context* context, grib_action* act)
{
grib_action_trigger* a = (grib_action_trigger*)act;
Assert(!"action_class_trigger::destroy: 'trigger' statement is deprecated");
#if 0
grib_action_trigger* a = (grib_action_trigger*)act;
grib_action* b = a->block;
while (b) {
@ -173,4 +182,5 @@ static void destroy(grib_context* context, grib_action* act)
grib_arguments_free(context, a->trigger_on);
grib_context_free_persistent(context, act->name);
grib_context_free_persistent(context, act->op);
#endif
}

View File

@ -82,16 +82,23 @@ static void init_class(grib_action_class* c)
static void dump(grib_action* act, FILE* f, int lvl)
{
Assert(!"action_class_while::dump: 'while' statement is deprecated");
#if 0
grib_action_while* a = (grib_action_while*)act;
int i = 0;
for (i = 0; i < lvl; i++)
grib_context_print(act->context, f, " ");
grib_context_print(act->context, f, "Loop %s\n", act->name);
grib_dump_action_branch(f, a->block_while, lvl + 1);
#endif
}
static int create_accessor(grib_section* p, grib_action* act, grib_loader* h)
{
Assert(!"action_class_while::create_accessor: 'while' statement is deprecated");
#if 0
grib_action_while* a = (grib_action_while*)act;
grib_accessor* ga = NULL;
@ -132,11 +139,15 @@ static int create_accessor(grib_section* p, grib_action* act, grib_loader* h)
next = next->next;
}
}
#endif
return GRIB_SUCCESS;
}
grib_action* grib_action_create_while(grib_context* context, grib_expression* expression, grib_action* block)
{
Assert(!"action_class_while::grib_action_create_while: 'while' statement is deprecated");
return NULL;
#if 0
char name[80];
const size_t nameLen = sizeof(name);
grib_action_while* a;
@ -147,7 +158,6 @@ grib_action* grib_action_create_while(grib_context* context, grib_expression* ex
a = (grib_action_while*)act;
act->next = NULL;
snprintf(name, nameLen, "_while%p", (void*)a);
act->name = grib_context_strdup_persistent(context, name);
act->op = grib_context_strdup_persistent(context, "section");
@ -157,10 +167,13 @@ grib_action* grib_action_create_while(grib_context* context, grib_expression* ex
grib_context_log(context, GRIB_LOG_DEBUG, " Action List %s is created \n", act->name);
return act;
#endif
}
static void destroy(grib_context* context, grib_action* act)
{
Assert(!"action_class_while::destroy: 'while' statement is deprecated");
#if 0
grib_action_while* self = (grib_action_while*)act;
grib_action* a = self->block_while;
@ -169,8 +182,8 @@ static void destroy(grib_context* context, grib_action* act)
grib_action_delete(context, a);
a = na;
}
grib_context_free_persistent(context, act->name);
grib_context_free_persistent(context, act->op);
grib_expression_free(context, self->expression);
#endif
}

View File

@ -742,6 +742,8 @@ static const char* codes_bufr_header_get_centre_name(long edition, long centre_c
return "wiix";
case 204:
return "niwa";
case 213:
return "birk";
case 214:
return "lemm";
case 215:

View File

@ -10,8 +10,8 @@
#include "grib_api_internal.h"
/* Input lon must be in degrees not radians */
/* Not to be used for latitudes as they can be -ve */
// Input lon must be in degrees not radians
// Not to be used for latitudes as they can be -ve
double normalise_longitude_in_degrees(double lon)
{
while (lon < 0)
@ -23,7 +23,7 @@ double normalise_longitude_in_degrees(double lon)
#ifdef ECCODES_ON_WINDOWS
/* Replace C99/Unix rint() for Windows Visual C++ (only before VC++ 2013 versions) */
// Replace C99/Unix rint() for Windows Visual C++ (only before VC++ 2013 versions)
#if defined _MSC_VER && _MSC_VER < 1800
double rint(double x)
{
@ -54,17 +54,17 @@ char get_dir_separator_char(void)
return DIR_SEPARATOR_CHAR;
}
/* Return 1 if the filepath is a regular file, 0 otherwise */
// Return 1 if the filepath is a regular file, 0 otherwise
int path_is_regular_file(const char* path)
{
struct stat s;
int stat_val = stat(path, &s);
if (stat_val != 0)
return 0; /*error doing stat*/
return S_ISREG(s.st_mode); /* 1 if it's a regular file */
return 0; // error doing stat
return S_ISREG(s.st_mode); // 1 if it's a regular file
}
/* Return 1 if the filepath is a directory, 0 otherwise */
// Return 1 if the filepath is a directory, 0 otherwise
int path_is_directory(const char* path)
{
struct stat s;
@ -79,13 +79,13 @@ int path_is_directory(const char* path)
char* codes_getenv(const char* name)
{
/* Look for the new ecCodes environment variable names */
/* if not found, then look for old grib_api ones for backward compatibility */
// Look for the new ecCodes environment variable names
// if not found, then look for old grib_api ones for backward compatibility
char* result = getenv(name);
if (result == NULL) {
const char* old_name = name;
/* Test the most commonly used variables first */
// Test the most commonly used variables first
if (STR_EQUAL(name, "ECCODES_SAMPLES_PATH"))
old_name = "GRIB_SAMPLES_PATH";
else if (STR_EQUAL(name, "ECCODES_DEFINITION_PATH"))
@ -141,7 +141,7 @@ int codes_check_grib_ieee_packing_value(int value)
return GRIB_SUCCESS;
}
/* Note: To be called in cases where we are WRITING a file (Do not call when reading) */
// Note: To be called in cases where we are WRITING a file (Do not call when reading)
int codes_flush_sync_close_file(FILE* f)
{
int err = 0;
@ -157,14 +157,14 @@ int codes_flush_sync_close_file(FILE* f)
#if 0
#ifdef HAVE_FCNTL_H
/* Heavy handed way of getting the file access mode: only proceed if writing */
// Heavy handed way of getting the file access mode: only proceed if writing
val = fcntl(fd, F_GETFL, 0);
if (val < 0) {
grib_context_log(c, GRIB_LOG_PERROR, "Call to fcntl failed");
return err;
}
if ((val & O_ACCMODE) != O_WRONLY) {
/* File is not being written */
// File is not being written
return GRIB_SUCCESS;
}
#endif
@ -214,3 +214,109 @@ int is_date_valid(long year, long month, long day, long hour, long minute, doubl
return 1;
}
static float float_epsilon(void)
{
float floatEps = 1.0;
while (1 + floatEps / 2 != 1)
floatEps /= 2;
return floatEps;
}
static int is_approximately_equal(double a, double b, double epsilon)
{
if (a == b)
return 1;
if (fabs(a - b) <= epsilon)
return 1;
return 0;
}
static double eval_value_factor(int64_t value, int64_t factor)
{
return (double)value * pow(10.0, -factor);
}
static int compute_scaled_value_and_scale_factor_algorithm1(
double input, int64_t maximum_value, int64_t maximum_factor,
int64_t* ret_value, int64_t* ret_factor)
{
int64_t factor = 0;
int64_t value = 0;
if (input == 0) {
*ret_factor = *ret_value = 0;
return GRIB_SUCCESS;
}
factor = floor(log10(maximum_value)) - floor(log10(input < 0 ? -input : input));
value = (int64_t)round(input * pow(10, factor));
while ((value % 10 == 0) && (factor > 0)) {
value /= 10;
factor--;
}
if (value >= maximum_value)
return GRIB_INTERNAL_ERROR;
if (factor > maximum_factor)
return GRIB_INTERNAL_ERROR;
*ret_factor = factor;
*ret_value = value;
return GRIB_SUCCESS;
}
static int compute_scaled_value_and_scale_factor_algorithm2(
double input, int64_t maximum_value, int64_t maximum_factor,
int64_t* ret_value, int64_t* ret_factor)
{
int64_t factor = 0, prev_factor = 0;
int64_t value = 0, prev_value = 0;
double exact = input;
const float epsilon = float_epsilon();
int is_negative = 0;
// Loop until we find a close enough approximation. Keep the last good values
if (exact < 0) {
is_negative = 1;
exact *= -1;
}
factor = prev_factor = 0;
value = prev_value = round(exact);
while (!is_approximately_equal(exact, eval_value_factor(value, factor), epsilon) &&
value < maximum_value &&
factor < maximum_factor) {
value = round(exact * pow(10., ++factor));
if (value > maximum_value || factor > maximum_factor) {
// One or more maxima exceeded. So stop and use the previous values
value = prev_value;
factor = prev_factor;
break;
}
prev_factor = factor;
prev_value = value;
}
if (is_negative) {
value *= -1;
}
if (value == 0)
return GRIB_INTERNAL_ERROR;
*ret_factor = factor;
*ret_value = value;
return GRIB_SUCCESS;
}
// Return GRIB_SUCCESS if no error and set the two outputs 'ret_value' and 'ret_factor'.
// ret_value cannot exceed scaled_value_max and ret_factor cannot exceed scale_factor_max
int compute_scaled_value_and_scale_factor(
double input, int64_t scaled_value_max, int64_t scale_factor_max,
int64_t* ret_value, int64_t* ret_factor)
{
int err = compute_scaled_value_and_scale_factor_algorithm1(input, scaled_value_max, scale_factor_max, ret_value, ret_factor);
if (err) {
err = compute_scaled_value_and_scale_factor_algorithm2(input, scaled_value_max, scale_factor_max, ret_value, ret_factor);
}
return err;
}

View File

@ -1450,6 +1450,7 @@ char* codes_getenv(const char* name);
int codes_check_grib_ieee_packing_value(int value);
int codes_flush_sync_close_file(FILE* f);
int is_date_valid(long year, long month, long day, long hour, long minute, double second);
int compute_scaled_value_and_scale_factor(double input, int64_t scaled_value_max, int64_t scale_factor_max, int64_t* ret_value, int64_t* ret_factor);
/* grib_util.cc*/
grib_handle* grib_util_sections_copy(grib_handle* hfrom, grib_handle* hto, int what, int* err);

View File

@ -178,10 +178,7 @@ static void compute_size(grib_accessor* a)
}
}
#if 0
printf("compute_size off=%ld slen=%ld a->offset=%ld\n",
(long)off,(long)slen,(long)a->offset);
#endif
// printf("compute_size off=%ld slen=%ld a->offset=%ld\n", (long)off,(long)slen,(long)a->offset);
a->length = off + (slen - a->offset);
@ -237,7 +234,7 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len)
return err;
if (*len < tlen) {
grib_context_log(a->context, GRIB_LOG_ERROR, "Wrong size for %s it contains %ld values", a->name, tlen);
grib_context_log(a->context, GRIB_LOG_ERROR, "Wrong size for %s, it contains %ld values", a->name, tlen);
*len = 0;
return GRIB_ARRAY_TOO_SMALL;
}
@ -315,7 +312,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len)
grib_handle* hand = grib_handle_of_accessor(a);
if (len[0] < (a->length)) {
grib_context_log(a->context, GRIB_LOG_ERROR, "unpack_string: Wrong size (%lu) for %s it contains %ld values",
grib_context_log(a->context, GRIB_LOG_ERROR, "unpack_string: Wrong size (%lu) for %s, it contains %ld values",
len[0], a->name, a->length);
len[0] = 0;
return GRIB_ARRAY_TOO_SMALL;

View File

@ -410,13 +410,20 @@ static int grib_concept_apply(grib_accessor* a, const char* name)
grib_get_string(h, "centre", centre_s, &centre_len) == GRIB_SUCCESS) {
grib_context_log(h->context, GRIB_LOG_ERROR, "concept: input handle edition=%ld, centre=%s", editionNumber, centre_s);
}
if (strcmp(act->name, "paramId") == 0 && string_to_long(name, &dummy) == GRIB_SUCCESS) {
grib_context_log(h->context, GRIB_LOG_ERROR,
"Please check the Parameter Database 'https://apps.ecmwf.int/codes/grib/param-db/?id=%s'", name);
if (strcmp(act->name, "paramId") == 0) {
if (string_to_long(name, &dummy) == GRIB_SUCCESS) {
// The paramId value is an integer. Show them the param DB
grib_context_log(h->context, GRIB_LOG_ERROR,
"Please check the Parameter Database 'https://codes.ecmwf.int/grib/param-db/?id=%s'", name);
} else {
// paramId being set to a non-integer
grib_context_log(h->context, GRIB_LOG_ERROR,
"The paramId value should be an integer. Are you trying to set the shortName?");
}
}
if (strcmp(act->name, "shortName") == 0) {
grib_context_log(h->context, GRIB_LOG_ERROR,
"Please check the Parameter Database 'https://apps.ecmwf.int/codes/grib/param-db/'");
"Please check the Parameter Database 'https://codes.ecmwf.int/grib/param-db/'");
}
/* Create a list of all possible values for this concept and sort it */

View File

@ -296,7 +296,7 @@ static int pack_double(grib_accessor* a, const double* val, size_t* len)
} else {
if (bits_per_value == 0) {
// ECC-1202: A non-constant field with bitsPerValue==0!
bits_per_value = 24; // Set sane value
bits_per_value = 24; //Set sane value
}
}

View File

@ -18,7 +18,7 @@
SUPER = grib_accessor_class_data_simple_packing
IMPLEMENTS = init
IMPLEMENTS = unpack_double
IMPLEMENTS = pack_double
IMPLEMENTS = pack_double;unpack_float
IMPLEMENTS = unpack_double_element;unpack_double_element_set
IMPLEMENTS = value_count
MEMBERS=const char* type_of_compression_used
@ -46,6 +46,7 @@ or edit "accessor.class" and rerun ./make_class.pl
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_float(grib_accessor*, float* val, size_t* len);
static int value_count(grib_accessor*, long*);
static void init(grib_accessor*, const long, grib_arguments*);
static void init_class(grib_accessor_class*);
@ -111,7 +112,7 @@ static grib_accessor_class _grib_accessor_class_data_jpeg2000_packing = {
&pack_double, /* grib_pack procedures double */
0, /* grib_pack procedures float */
&unpack_double, /* grib_unpack procedures double */
0, /* grib_unpack procedures float */
&unpack_float, /* grib_unpack procedures float */
0, /* grib_pack procedures string */
0, /* grib_unpack procedures string */
0, /* grib_pack array procedures string */
@ -153,7 +154,6 @@ static void init_class(grib_accessor_class* c)
c->pack_long = (*(c->super))->pack_long;
c->unpack_long = (*(c->super))->unpack_long;
c->pack_float = (*(c->super))->pack_float;
c->unpack_float = (*(c->super))->unpack_float;
c->pack_string = (*(c->super))->pack_string;
c->unpack_string = (*(c->super))->unpack_string;
c->pack_string_array = (*(c->super))->pack_string_array;
@ -251,6 +251,11 @@ static int value_count(grib_accessor* a, long* n_vals)
#define EXTRA_BUFFER_SIZE 10240
#if HAVE_JPEG
static int unpack_float(grib_accessor*, float* val, size_t* len)
{
return GRIB_NOT_IMPLEMENTED;
}
static int unpack_double(grib_accessor* a, double* val, size_t* len)
{
grib_accessor_data_jpeg2000_packing* self = (grib_accessor_data_jpeg2000_packing*)a;
@ -578,6 +583,11 @@ cleanup:
}
#else
static int unpack_float(grib_accessor* a, float* val, size_t* len)
{
grib_context_log(a->context, GRIB_LOG_ERROR, "JPEG support not enabled.");
return GRIB_FUNCTIONALITY_NOT_ENABLED;
}
static int unpack_double(grib_accessor* a, double* val, size_t* len)
{
grib_context_log(a->context, GRIB_LOG_ERROR, "JPEG support not enabled.");

View File

@ -156,118 +156,23 @@ static void init(grib_accessor* a, const long l, grib_arguments* c)
grib_handle* hand = grib_handle_of_accessor(a);
self->scaleFactor = grib_arguments_get_name(hand, c, n++);
self->scaledValue = grib_arguments_get_name(hand, c, n++); /* Can be scalar or array */
self->scaledValue = grib_arguments_get_name(hand, c, n++); // Can be scalar or array
/* ECC-979: Allow user to encode */
/* a->flags |= GRIB_ACCESSOR_FLAG_READ_ONLY; */
}
static float float_epsilon(void)
{
float floatEps = 1.0;
while (1 + floatEps / 2 != 1)
floatEps /= 2;
return floatEps;
}
static int is_approximately_equal(double a, double b, double epsilon)
{
if (a == b)
return 1;
if (fabs(a - b) <= epsilon)
return 1;
return 0;
}
static double eval_value_factor(int64_t value, int64_t factor)
{
return (double)value * pow(10.0, -factor);
}
/* Return 0 if no error and set the two outputs 'value' and 'factor'
* value cannot exceed maximum_value and factor cannot exceed maximum_factor
*/
static int get_scaled_value_and_scale_factor_algorithm1(
double input, int64_t maximum_value, int64_t maximum_factor,
int64_t* ret_value, int64_t* ret_factor)
{
int64_t factor = 0;
int64_t value = 0;
factor = floor(log10(maximum_value)) - floor(log10(input < 0 ? -input : input));
value = (int64_t)round(input * pow(10, factor));
while ((value % 10 == 0) && (factor > 0)) {
value /= 10;
factor--;
}
if (value >= maximum_value)
return GRIB_INTERNAL_ERROR;
if (factor > maximum_factor)
return GRIB_INTERNAL_ERROR;
*ret_factor = factor;
*ret_value = value;
return GRIB_SUCCESS;
}
/* Return 0 if no error and set the two outputs 'value' and 'factor'
* value cannot exceed maximum_value and factor cannot exceed maximum_factor
*/
static int get_scaled_value_and_scale_factor_algorithm2(
double input, int64_t maximum_value, int64_t maximum_factor,
int64_t* ret_value, int64_t* ret_factor)
{
int64_t factor = 0, prev_factor = 0;
int64_t value = 0, prev_value = 0;
double exact = input;
const float epsilon = float_epsilon();
int is_negative = 0;
/* Loop until we find a close enough approximation. Keep the last good values */
if (exact < 0) {
is_negative = 1;
exact *= -1;
}
factor = prev_factor = 0;
value = prev_value = round(exact);
while (!is_approximately_equal(exact, eval_value_factor(value, factor), epsilon) &&
value < maximum_value &&
factor < maximum_factor) {
value = round(exact * pow(10., ++factor));
if (value > maximum_value || factor > maximum_factor) {
/* One or more maxima exceeded. So stop and use the previous values */
value = prev_value;
factor = prev_factor;
break;
}
prev_factor = factor;
prev_value = value;
}
if (is_negative) {
value *= -1;
}
if (value == 0)
return GRIB_INTERNAL_ERROR;
*ret_factor = factor;
*ret_value = value;
return GRIB_SUCCESS;
// ECC-979: Allow user to encode
// a->flags |= GRIB_ACCESSOR_FLAG_READ_ONLY;
}
static int pack_double(grib_accessor* a, const double* val, size_t* len)
{
/* See ECC-979 and ECC-1416 */
/* Evaluate self->scaleFactor and self->scaledValue from input double '*val' */
// See ECC-979 and ECC-1416
// Evaluate self->scaleFactor and self->scaledValue from input double '*val'
grib_accessor_from_scale_factor_scaled_value* self = (grib_accessor_from_scale_factor_scaled_value*)a;
grib_handle* hand = grib_handle_of_accessor(a);
int err = 0;
int64_t factor = 0;
int64_t value = 0;
double exact = *val; /*the input*/
int64_t maxval_value, maxval_factor; /*maximum allowable values*/
double exact = *val; // the input
int64_t maxval_value, maxval_factor; // maximum allowable values
int value_accessor_num_bits = 0, factor_accessor_num_bits = 0;
grib_accessor *factor_accessor, *value_accessor;
@ -295,19 +200,16 @@ static int pack_double(grib_accessor* a, const double* val, size_t* len)
}
value_accessor_num_bits = value_accessor->length * 8;
factor_accessor_num_bits = factor_accessor->length * 8;
maxval_value = (1UL << value_accessor_num_bits) - 2; /* exclude missing */
maxval_factor = (1UL << factor_accessor_num_bits) - 2; /* exclude missing */
maxval_value = (1UL << value_accessor_num_bits) - 2; // exclude missing
maxval_factor = (1UL << factor_accessor_num_bits) - 2; // exclude missing
if (strcmp(factor_accessor->cclass->name,"signed")==0) {
maxval_factor = (1UL << (factor_accessor_num_bits - 1)) - 1;
}
err = get_scaled_value_and_scale_factor_algorithm1(exact, maxval_value, maxval_factor, &value, &factor);
err = compute_scaled_value_and_scale_factor(exact, maxval_value, maxval_factor, &value, &factor);
if (err) {
err = get_scaled_value_and_scale_factor_algorithm2(exact, maxval_value, maxval_factor, &value, &factor);
if (err) {
grib_context_log(a->context, GRIB_LOG_ERROR, "Failed to compute %s and %s from %g", self->scaleFactor, self->scaledValue, exact);
return err;
}
grib_context_log(a->context, GRIB_LOG_ERROR, "Failed to compute %s and %s from %g", self->scaleFactor, self->scaledValue, exact);
return err;
}
if ((err = grib_set_long_internal(hand, self->scaleFactor, factor)) != GRIB_SUCCESS)
@ -342,7 +244,7 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len)
*len = 1;
return GRIB_SUCCESS;
} else {
/* ECC-966: If scale factor is missing, print error and treat it as zero (as a fallback) */
// ECC-966: If scale factor is missing, print error and treat it as zero (as a fallback)
if (grib_is_missing(hand, self->scaleFactor, &err) && err == GRIB_SUCCESS) {
grib_context_log(a->context, GRIB_LOG_ERROR,
"unpack_double for %s: %s is missing! Using zero instead", a->name, self->scaleFactor);
@ -352,9 +254,9 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len)
*val = scaledValue;
/* The formula is:
* real_value = scaled_value / pow(10, scale_factor)
*/
// The formula is:
// real_value = scaled_value / pow(10, scale_factor)
//
while (scaleFactor < 0) {
*val *= 10;
scaleFactor++;

View File

@ -165,6 +165,14 @@ static void dump(grib_accessor* a, grib_dumper* dumper)
grib_dump_long(dumper, a, NULL);
}
static bool is_tigge(grib_handle* h)
{
long productionStatus = 0;
int err = grib_get_long(h, "productionStatusOfProcessedData", &productionStatus);
if (err) return false;
return (productionStatus == 4 || productionStatus == 5);
}
static int unpack_double(grib_accessor* a, double* val, size_t* len)
{
int ret = 0;
@ -176,6 +184,7 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len)
long value_first = 0;
char pressure_units[10] = {0,};
size_t pressure_units_len = 10;
bool tigge = is_tigge(hand);
double v;
@ -200,9 +209,13 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len)
v = value_first;
if (scale_first != GRIB_MISSING_LONG) {
// GRIB-637 Potential vorticity surface
// GRIB-637, ECC-1081: Potential vorticity surface
if (type_first == 109) {
scale_first -= 6;
if (tigge) {
scale_first -= 6; // TIGGE data follows different rules
} else {
scale_first -= 9;
}
}
while (scale_first < 0 && v != 0) {
@ -251,13 +264,18 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len)
static int pack_double(grib_accessor* a, const double* val, size_t* len)
{
grib_accessor_g2level* self = (grib_accessor_g2level*)a;
grib_handle* hand = grib_handle_of_accessor(a);
int ret = 0;
double value_first = *val;
long scale_first = 0;
long type_first = 0;
char pressure_units[10] = {0,};
size_t pressure_units_len = 10;
grib_handle* hand = grib_handle_of_accessor(a);
int ret = 0;
double value_first = *val;
//long scale_first = 0;
long type_first = 0;
char pressure_units[10] = {0,};
size_t pressure_units_len = 10;
const long lval = (long)value_first;
if (value_first == lval) { // input is a whole number; process it as an integer
return pack_long(a, &lval, len);
}
if (*len != 1)
return GRIB_WRONG_ARRAY_SIZE;
@ -277,20 +295,29 @@ static int pack_double(grib_accessor* a, const double* val, size_t* len)
default:
break;
}
//
// final = scaled_value * 10 ^ -scale_factor
// = scaled_value / (10^scale_factor)
//
// Choose 2 decimal places
//
scale_first = 2;
value_first *= 100;
value_first = value_first + 0.5; /* round up */
//scale_first = 2;
//value_first *= 100;
//value_first = value_first + 0.5; //round up
// TODO(masn): These maxima should come from the respective accessors
const int64_t scaled_value_max = (1UL << 32) - 1; // scaledValueOf*FixedSurface is 4 octets
const int64_t scale_factor_max = (1UL << 8) - 1; // scaleFactorOf*FixedSurface is 1 octet
int64_t lscaled_value=0, lscale_factor=0;
ret = compute_scaled_value_and_scale_factor(value_first, scaled_value_max, scale_factor_max, &lscaled_value, &lscale_factor);
if (ret) {
grib_context_log(a->context, GRIB_LOG_ERROR, "Key %s (unpack_double): Failed to compute %s and %s from %g",
a->name, self->scale_first, self->value_first, value_first);
return ret;
}
if (type_first > 9) {
if ((ret = grib_set_long_internal(hand, self->scale_first, scale_first)) != GRIB_SUCCESS)
if ((ret = grib_set_long_internal(hand, self->scale_first, (long)lscale_factor)) != GRIB_SUCCESS)
return ret;
if ((ret = grib_set_long_internal(hand, self->value_first, (long)value_first)) != GRIB_SUCCESS)
if ((ret = grib_set_long_internal(hand, self->value_first, (long)lscaled_value)) != GRIB_SUCCESS)
return ret;
}
@ -303,13 +330,13 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len)
long value_first = *val;
long scale_first = 0;
long type_first = 0;
long levelFactor = 1;
char pressure_units[10] = {0,};
size_t pressure_units_len = 10;
grib_accessor_g2level* self = (grib_accessor_g2level*)a;
grib_handle* hand = grib_handle_of_accessor(a);
int change_scale_and_value = 1;
bool tigge = is_tigge(hand);
if (*len != 1)
return GRIB_WRONG_ARRAY_SIZE;
@ -335,11 +362,13 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len)
if (!strcmp(pressure_units, "hPa"))
value_first *= 100;
break;
case 109:
if ((ret = grib_get_long(hand, "levelFactor", &levelFactor)) == GRIB_SUCCESS) {
// See ECC-1081
scale_first = levelFactor;
case 109: // Potential vorticity surface (See ECC-1081)
if (!tigge) {
scale_first = 9;
} else {
scale_first = 6; // TIGGE data follows different rules
}
break;
default:
break;

View File

@ -17,6 +17,8 @@
#include <typeinfo>
#include <limits>
#include <cassert>
#include <type_traits>
/*
This is used by make_class.pl
@ -317,6 +319,7 @@ static int unpack_long(grib_accessor* a, long* v, size_t* len)
template <typename T>
static int unpack(grib_accessor* a, T* v, size_t* len)
{
static_assert(std::is_floating_point<T>::value, "Requires floating point numbers");
int type = GRIB_TYPE_UNDEFINED;
if (a->cclass->unpack_long && a->cclass->unpack_long != &unpack_long) {
long val = 0;

View File

@ -1,53 +0,0 @@
// ECC-1467
#pragma once
#include "grib_api_internal_cpp.h"
#include <type_traits>
#include <typeinfo>
template <typename T>
class GribAccessorClassGen {
public:
static int unpack(grib_accessor* a, T* v, size_t* len);
};
template <> int GribAccessorClassGen<long>::unpack(grib_accessor* a, long* v, size_t* len);
template <> int GribAccessorClassGen<char>::unpack(grib_accessor* a, char* v, size_t* len);
template <> int GribAccessorClassGen<float>::unpack(grib_accessor* a, float* v, size_t* len);
template <typename T>
int GribAccessorClassGen<T>::unpack(grib_accessor* a, T* v, size_t* len)
{
static_assert(std::is_floating_point<T>::value, "Requires floating point numbers");
int type = GRIB_TYPE_UNDEFINED;
if (a->cclass->unpack_long && a->cclass->unpack_long != &GribAccessorClassGen<long>::unpack) {
long val = 0;
size_t l = 1;
grib_unpack_long(a, &val, &l);
*v = val;
grib_context_log(a->context, GRIB_LOG_DEBUG, "Casting long %s to %s", a->name, typeid(T).name());
return GRIB_SUCCESS;
}
if (a->cclass->unpack_string && a->cclass->unpack_string != &GribAccessorClassGen<char>::unpack) {
char val[1024];
size_t l = sizeof(val);
char* last = NULL;
grib_unpack_string(a, val, &l);
*v = strtod(val, &last);
if (*last == 0) { /* conversion of string to double worked */
grib_context_log(a->context, GRIB_LOG_DEBUG, "Casting string %s to long", a->name);
return GRIB_SUCCESS;
}
}
grib_context_log(a->context, GRIB_LOG_ERROR, "Cannot unpack %s as %s", a->name, typeid(T).name());
if (grib_get_native_type(grib_handle_of_accessor(a), a->name, &type) == GRIB_SUCCESS) {
grib_context_log(a->context, GRIB_LOG_ERROR, "Hint: Try unpacking as %s", grib_get_type_name(type));
}
return GRIB_NOT_IMPLEMENTED;
}

View File

@ -240,14 +240,14 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len)
dlonlast = ((double)lonlast) / factor;
if (N == 0) {
grib_context_log(c, GRIB_LOG_ERROR, "global_gaussian unpack_long: N cannot be 0!");
grib_context_log(c, GRIB_LOG_ERROR, "Key %s (unpack_long): N cannot be 0!", a->name);
return GRIB_WRONG_GRID;
}
lats = (double*)grib_context_malloc(c, sizeof(double) * N * 2);
if (!lats) {
grib_context_log(c, GRIB_LOG_ERROR,
"global_gaussian unpack_long: Memory allocation error: %ld bytes", sizeof(double) * N * 2);
"Key %s (unpack_long): Memory allocation error: %zu bytes", a->name, sizeof(double) * N * 2);
return GRIB_OUT_OF_MEMORY;
}
if ((ret = grib_get_gaussian_latitudes(N, lats)) != GRIB_SUCCESS)
@ -333,7 +333,7 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len)
lats = (double*)grib_context_malloc(c, sizeof(double) * N * 2);
if (!lats) {
grib_context_log(c, GRIB_LOG_ERROR,
"global_gaussian pack_long: Memory allocation error: %zu bytes", sizeof(double) * N * 2);
"Key %s (pack_long): Memory allocation error: %zu bytes", a->name, sizeof(double) * N * 2);
return GRIB_OUT_OF_MEMORY;
}
if ((ret = grib_get_gaussian_latitudes(N, lats)) != GRIB_SUCCESS)

View File

@ -168,7 +168,6 @@ struct proj_mapping
};
typedef struct proj_mapping proj_mapping;
// This should only be called for GRID POINT data (not spherical harmonics etc)
static int get_major_minor_axes(grib_handle* h, double* pMajor, double* pMinor)
{
@ -221,6 +220,7 @@ static int proj_space_view(grib_handle* h, char* result)
return err;
#endif
}
static int proj_albers(grib_handle* h, char* result)
{
return GRIB_NOT_IMPLEMENTED;
@ -294,19 +294,18 @@ static int proj_polar_stereographic(grib_handle* h, char* result)
return err;
}
#if 0
// ECC-1552: This is for regular_ll, regular_gg, reduced_ll, reduced_gg
// These are not 'projected' grids!
static int proj_unprojected(grib_handle* h, char* result)
{
int err = 0;
char shape[64] = {0,};
if ((err = get_earth_shape(h, shape)) != GRIB_SUCCESS)
return err;
//char shape[64] = {0,};
//if ((err = get_earth_shape(h, shape)) != GRIB_SUCCESS) return err;
//snprintf(result, 1024, "+proj=longlat %s", shape);
snprintf(result, 1024, "+proj=longlat +datum=WGS84 +no_defs +type=crs");
snprintf(result, 1024, "+proj=longlat %s", shape);
return err;
}
#endif
static int proj_mercator(grib_handle* h, char* result)
{
@ -325,10 +324,10 @@ static int proj_mercator(grib_handle* h, char* result)
#define NUMBER(a) (sizeof(a) / sizeof(a[0]))
static proj_mapping proj_mappings[] = {
// { "regular_ll", &proj_unprojected },
// { "regular_gg", &proj_unprojected },
// { "reduced_ll", &proj_unprojected },
// { "reduced_gg", &proj_unprojected },
{ "regular_ll", &proj_unprojected },
{ "regular_gg", &proj_unprojected },
{ "reduced_ll", &proj_unprojected },
{ "reduced_gg", &proj_unprojected },
{ "mercator", &proj_mercator },
{ "lambert", &proj_lambert_conformal },

View File

@ -182,7 +182,7 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len)
/* We ignore the 'seconds' in our time calculation! */
if (second != 0) {
grib_context_log(a->context, GRIB_LOG_ERROR,
"Truncating time: non-zero seconds(%ld) ignored", second);
"Key %s (unpack_long): Truncating time: non-zero seconds(%ld) ignored", a->name, second);
}
if (*len < 1)
@ -236,7 +236,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len)
unpack_long(a, &v, &lsize);
if (*len < 5) {
grib_context_log(a->context, GRIB_LOG_ERROR, "grib_accessor_time : unpack_string : Buffer too small for %s", a->name);
grib_context_log(a->context, GRIB_LOG_ERROR, "Key %s (unpack_string): Buffer too small", a->name);
*len = 5;
return GRIB_BUFFER_TOO_SMALL;

View File

@ -1118,6 +1118,7 @@ struct grib_context
int bufr_set_to_missing_if_out_of_range;
int bufr_multi_element_constant_arrays;
int grib_data_quality_checks;
int single_precision;
FILE* log_stream;
grib_trie* classes;
grib_trie* lists;

View File

@ -350,25 +350,26 @@ static grib_context default_grib_context = {
0, /* keys_count */
0, /* concepts_index */
0, /* concepts_count */
{0,}, /* concepts */
0, /* hash_array_index */
0, /* hash_array_count */
{0,}, /* hash_array */
0, /* def_files */
0, /* blocklist */
0, /* ieee_packing */
0, /* bufrdc_mode */
0, /* bufr_set_to_missing_if_out_of_range */
0, /* bufr_multi_element_constant_arrays */
0, /* grib_data_quality_checks */
0, /* log_stream */
0, /* classes */
0, /* lists */
0, /* expanded_descriptors */
{0,}, /* concepts */
0, /* hash_array_index */
0, /* hash_array_count */
{0,}, /* hash_array */
0, /* def_files */
0, /* blocklist */
0, /* ieee_packing */
0, /* bufrdc_mode */
0, /* bufr_set_to_missing_if_out_of_range */
0, /* bufr_multi_element_constant_arrays */
0, /* grib_data_quality_checks */
0, /* single_precision */
0, /* log_stream */
0, /* classes */
0, /* lists */
0, /* expanded_descriptors */
DEFAULT_FILE_POOL_MAX_OPENED_FILES /* file_pool_max_opened_files */
#if GRIB_PTHREADS
,
PTHREAD_MUTEX_INITIALIZER /* mutex */
PTHREAD_MUTEX_INITIALIZER /* mutex */
#endif
};
@ -396,6 +397,7 @@ grib_context* grib_context_get_default()
const char* bufr_set_to_missing_if_out_of_range = NULL;
const char* bufr_multi_element_constant_arrays = NULL;
const char* grib_data_quality_checks = NULL;
const char* single_precision = NULL;
const char* file_pool_max_opened_files = NULL;
#ifdef ENABLE_FLOATING_POINT_EXCEPTIONS
@ -407,6 +409,7 @@ grib_context* grib_context_get_default()
bufr_set_to_missing_if_out_of_range = getenv("ECCODES_BUFR_SET_TO_MISSING_IF_OUT_OF_RANGE");
bufr_multi_element_constant_arrays = getenv("ECCODES_BUFR_MULTI_ELEMENT_CONSTANT_ARRAYS");
grib_data_quality_checks = getenv("ECCODES_GRIB_DATA_QUALITY_CHECKS");
single_precision = getenv("ECCODES_SINGLE_PRECISION");
large_constant_fields = codes_getenv("ECCODES_GRIB_LARGE_CONSTANT_FIELDS");
no_abort = codes_getenv("ECCODES_NO_ABORT");
debug = codes_getenv("ECCODES_DEBUG");
@ -550,6 +553,7 @@ grib_context* grib_context_get_default()
default_grib_context.bufr_set_to_missing_if_out_of_range = bufr_set_to_missing_if_out_of_range ? atoi(bufr_set_to_missing_if_out_of_range) : 0;
default_grib_context.bufr_multi_element_constant_arrays = bufr_multi_element_constant_arrays ? atoi(bufr_multi_element_constant_arrays) : 0;
default_grib_context.grib_data_quality_checks = grib_data_quality_checks ? atoi(grib_data_quality_checks) : 0;
default_grib_context.single_precision = single_precision ? atoi(single_precision) : 0;
default_grib_context.file_pool_max_opened_files = file_pool_max_opened_files ? atoi(file_pool_max_opened_files) : DEFAULT_FILE_POOL_MAX_OPENED_FILES;
}

View File

@ -373,6 +373,7 @@ static grib_fieldset* grib_fieldset_create_from_keys(grib_context* c, const char
else {
type = default_type;
}
//if (type==0) type = default_type;
*err = grib_fieldset_new_column(set, i, key, type);
grib_context_free(c, key);
}
@ -925,6 +926,10 @@ static int grib_fieldset_set_order_by(grib_fieldset* set, grib_order_by* ob)
if (*p == ':')
*p = 0;
for (i = 0; i < set->columns_size; i++) {
if (!set->columns[i].name) { //ECC-1562
grib_context_log(set->context, GRIB_LOG_ERROR, "grib_fieldset_set_order_by: Invalid type for key=%s", next->key);
return GRIB_INVALID_TYPE;
}
if (!grib_inline_strcmp(next->key, set->columns[i].name)) {
next->idkey = i;
break;
@ -933,7 +938,7 @@ static int grib_fieldset_set_order_by(grib_fieldset* set, grib_order_by* ob)
if (next->idkey == -1) {
grib_context_log(set->context, GRIB_LOG_ERROR,
"grib_fieldset_set_order_by: "
"Unable to apply the order by. Key missing from the fieldset.\n");
"Unable to apply the order by. Key missing from the fieldset.");
return GRIB_MISSING_KEY;
}
next = next->next;

View File

@ -660,6 +660,8 @@ static grib_handle* grib_handle_new_from_file_multi(grib_context* c, FILE* f, in
char *gts_header = 0, *save_gts_header = 0;
int gtslen = 0;
*error = GRIB_SUCCESS;
if (c == NULL)
c = grib_context_get_default();

File diff suppressed because it is too large Load Diff

View File

@ -8,10 +8,6 @@
* virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
*/
/**************************************
* Enrico Fucile
**************************************/
static const int mapping[] = {
0, /* 00 */
0, /* 01 */

View File

@ -162,9 +162,13 @@ int grib_init_accessor_from_handle(grib_loader* loader, grib_accessor* ga, grib_
pack_missing = 1;
}
switch (grib_accessor_get_native_type(ga)) {
case GRIB_TYPE_STRING:
long ga_type = grib_accessor_get_native_type(ga);
if (STR_EQUAL(name,"level")) { // See ECC-1560
ga_type = GRIB_TYPE_DOUBLE;
}
switch (ga_type) {
case GRIB_TYPE_STRING:
/*ecc__grib_get_string_length(ga,&len); See ECC-490 */
grib_get_string_length(h, name, &len);
sval = (char*)grib_context_malloc(h->context, len);

View File

@ -2142,8 +2142,11 @@ int grib_util_grib_data_quality_check(grib_handle* h, double min_val, double max
bool is_error = true;
char description[1024] = {0,};
char step[32] = "unknown";
char shortName[32] = {0,};
size_t len = 32;
char shortName[64] = {0,};
char name[526] = {0,};
size_t len = 0;
const char* invalid_shortName = "unknown";
const char* invalid_name = "Experimental product";
// If grib_data_quality_checks == 1, limits failure results in an error
// If grib_data_quality_checks == 2, limits failure results in a warning
@ -2151,10 +2154,19 @@ int grib_util_grib_data_quality_check(grib_handle* h, double min_val, double max
Assert(ctx->grib_data_quality_checks == 1 || ctx->grib_data_quality_checks == 2);
is_error = (ctx->grib_data_quality_checks == 1);
len = sizeof(shortName);
err = grib_get_string(h, "shortName", shortName, &len);
if (err || STR_EQUAL(shortName, "unknown")) {
fprintf(stderr, "ECCODES %s : Invalid metadata: shortName=unknown\n",
(is_error ? "ERROR" : "WARNING"));
if (err || STR_EQUAL(shortName, invalid_shortName)) {
fprintf(stderr, "ECCODES %s : Invalid metadata: shortName='%s'\n",
(is_error ? "ERROR" : "WARNING"), invalid_shortName);
if (is_error) return GRIB_INVALID_MESSAGE;
}
len = sizeof(name);
err = grib_get_string(h, "name", name, &len);
if (err || STR_EQUAL(name, invalid_name)) {
fprintf(stderr, "ECCODES %s : Invalid metadata: name='%s'\n",
(is_error ? "ERROR" : "WARNING"), invalid_name);
if (is_error) return GRIB_INVALID_MESSAGE;
}

View File

@ -9,13 +9,10 @@
*/
/***************************************************************************
* Jean Baptiste Filippi - 01.11.2005
* Enrico Fucile *
***************************************************************************/
#include "grib_api_internal_cpp.h"
#include <float.h>
/* Note: A fast cut-down version of strcmp which does NOT return -1 */
/* 0 means input strings are equal and 1 means not equal */
GRIB_INLINE static int grib_inline_strcmp(const char* a, const char* b)

View File

@ -166,7 +166,7 @@ int string_count_char(const char* str, char c)
{
int i = 0, count = 0;
DebugAssert(str);
for(i=0; str[i]; i++) {
for (i=0; str[i]; i++) {
if (str[i] == c) count++;
}
return count;
@ -213,7 +213,7 @@ const char* grib_get_type_name(int type)
/* Replace all occurrences of character in string.
* Returns pointer to the NUL byte at the end of 's'
*/
char *string_replace_char(char *s, char oldc, char newc)
char* string_replace_char(char *s, char oldc, char newc)
{
for (; *s; ++s)
if (*s == oldc)
@ -222,9 +222,10 @@ char *string_replace_char(char *s, char oldc, char newc)
}
/* Remove all instances of character 'c' from 'str' */
void string_remove_char(char * str, char c)
void string_remove_char(char* str, char c)
{
size_t i, j;
DebugAssert(str);
size_t len = strlen(str);
for(i=0; i<len; i++) {
if(str[i] == c) {

View File

@ -108,6 +108,7 @@ if( HAVE_BUILD_TOOLS )
grib_ecc-1322
grib_ecc-1319
grib_ecc-1406
grib_ecc-1560
bufr_ecc-1028
bufr_ecc-1195
bufr_ecc-1259

View File

@ -16,6 +16,7 @@ temp1=temp1.$label.grib2
temp2=temp2.$label.grib2
temp=temp.$label.grib2
tempFilt=temp.$label.filt
tempText=temp.$label.txt
sample2=$ECCODES_SAMPLES_PATH/GRIB2.tmpl
@ -119,4 +120,21 @@ $tools_dir/grib_set -s tablesVersion=26,productDefinitionTemplateNumber=85 $samp
$tools_dir/grib_compare -b productDefinitionTemplateNumber $temp1 $temp2
rm -f $temp $temp1 $temp2 $tempFilt
# ECC-1564: Support local product definition templates for different centres
$tools_dir/grib_set -s productDefinitionTemplateNumber=40033 $sample2 $temp
$tools_dir/grib_set -s productDefinitionTemplateNumber=40034 $sample2 $temp
# ECC-1563: new local section 4 templates for extra large ensembles
$tools_dir/grib_set -s localTablesVersion=1,productDefinitionTemplateNumber=65533,perturbationNumber=2e8 $sample2 $temp
grib_check_key_equals $temp perturbationNumber '200000000'
$tools_dir/grib_dump -O -p section_4 $temp > $tempText
grep -q "Individual member for large ensemble forecast.*point in time" $tempText
$tools_dir/grib_set -s localTablesVersion=1,productDefinitionTemplateNumber=65534,perturbationNumber=2e8 $sample2 $temp
grib_check_key_equals $temp perturbationNumber,typeOfStatisticalProcessing '200000000 255'
$tools_dir/grib_dump -O -p section_4 $temp > $tempText
grep -q "Individual member for large ensemble forecast.*continuous or non-continuous interval" $tempText
# Clean up
rm -f $temp $temp1 $temp2 $tempFilt $tempText

View File

@ -209,7 +209,8 @@ if [ $HAVE_AEC -eq 1 ]; then
[ $status -ne 0 ]
fi
# Invalid shortName
# Invalid shortName/name
# -------------------------
export ECCODES_GRIB_DATA_QUALITY_CHECKS=1
input2=${data_dir}/reduced_gaussian_surface.grib2
${tools_dir}/grib_set -s discipline=254 $input2 $tempOut
@ -219,7 +220,19 @@ ${tools_dir}/grib_set -s scaleValuesBy=2 $tempOut $tempGrib2 2>$tempErr
status=$?
set -e
[ $status -ne 0 ]
grep -q "Invalid metadata: shortName=unknown" $tempErr
grep -q "Invalid metadata: shortName='unknown'" $tempErr
# Invalid name (ECC-793)
${tools_dir}/grib_set -s paramId=129080 $input2 $tempOut 2>$tempErr
grib_check_key_equals $tempOut 'name' 'Experimental product'
# Repacking causes the values to be set
set +e
${tools_dir}/grib_set -r -s paramId=129080 $input2 $tempOut 2>$tempErr
status=$?
set -e
[ $status -ne 0 ]
grep -q "Invalid metadata: name='Experimental product'" $tempErr
# Clean up
rm -rf $tempDir

50
tests/grib_ecc-1560.sh Executable file
View File

@ -0,0 +1,50 @@
#!/bin/sh
# (C) Copyright 2005- 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.ctest.sh
REDIRECT=/dev/null
label="grib_ecc-1560_test"
temp_PDTN08_Grib=temp.$label.PDTN08.grib
temp_PDTN11_Grib=temp.$label.PDTN11.grib
tempGrib=temp.$label.grib
sample_grib2=$ECCODES_SAMPLES_PATH/GRIB2.tmpl
# We set PDTN=8 and level to 1.5 metres above ground
${tools_dir}/grib_set -s \
productDefinitionTemplateNumber=8,typeOfFirstFixedSurface=103,scaledValueOfFirstFixedSurface=15,scaleFactorOfFirstFixedSurface=1 \
$sample_grib2 $temp_PDTN08_Grib
grib_check_key_equals $temp_PDTN08_Grib level:d 1.5
# Now we change to PDTN 11
${tools_dir}/grib_set -s productDefinitionTemplateNumber=11 $temp_PDTN08_Grib $temp_PDTN11_Grib
grib_check_key_equals $temp_PDTN11_Grib level:d 1.5
grib_check_key_equals $temp_PDTN11_Grib scaledValueOfFirstFixedSurface 15
grib_check_key_equals $temp_PDTN11_Grib scaleFactorOfFirstFixedSurface 1
# Set whole value using the int/double encoding
# -----------------------------------------------
${tools_dir}/grib_set -s typeOfFirstFixedSurface=105,level:i=34 $sample_grib2 $tempGrib
grib_check_key_equals $tempGrib scaleFactorOfFirstFixedSurface 0
grib_check_key_equals $tempGrib scaledValueOfFirstFixedSurface 34
${tools_dir}/grib_set -s typeOfFirstFixedSurface=105,level:d=34 $sample_grib2 $tempGrib
grib_check_key_equals $tempGrib scaleFactorOfFirstFixedSurface 0
grib_check_key_equals $tempGrib scaledValueOfFirstFixedSurface 34
${tools_dir}/grib_set -s typeOfFirstFixedSurface=105,level:d=3.456 $sample_grib2 $tempGrib
grib_check_key_equals $tempGrib scaleFactorOfFirstFixedSurface 3
grib_check_key_equals $tempGrib scaledValueOfFirstFixedSurface 3456
# Clean up
rm -f $temp_PDTN08_Grib $temp_PDTN11_Grib $tempGrib

View File

@ -199,11 +199,20 @@ cat >$tempFilt <<EOF
switch (edition) {
case 1: print "1";
case 2: print "2";
default: print "what is this?";assert(0);
default: print "[file]: what is this?"; assert(0);
}
EOF
${tools_dir}/grib_filter $tempFilt $ECCODES_SAMPLES_PATH/GRIB1.tmpl $ECCODES_SAMPLES_PATH/GRIB2.tmpl
cat >$tempFilt <<EOF
switch (packingType) {
case "grid_simple": print "simple";
case "grid_ccsds": print "ccsds";
case "spectral_complex": print "spectral";
default: print "[file]: what is this?"; assert(0);
}
EOF
${tools_dir}/grib_filter $tempFilt $data_dir/sample.grib2 ${data_dir}/ccsds.grib2 $data_dir/spherical_model_level.grib2
echo "Test MISSING"
# -----------------

View File

@ -15,6 +15,7 @@ sample_g1=$ECCODES_SAMPLES_PATH/GRIB1.tmpl
sample_g2=$ECCODES_SAMPLES_PATH/GRIB2.tmpl
temp=temp.level.grib
temp2=temp2.level.grib
temp3=temp3.level.grib
file=${data_dir}/regular_gaussian_pressure_level.grib1
@ -64,13 +65,13 @@ diff temp.level.good test.dump
${tools_dir}/grib_set -s typeOfFirstFixedSurface=103,level=24 $sample_g2 $temp
grib_check_key_equals $temp level,scaledValueOfFirstFixedSurface,scaleFactorOfFirstFixedSurface '24 24 0'
${tools_dir}/grib_set -s typeOfFirstFixedSurface=103,level=2.4 $sample_g2 $temp
grib_check_key_equals $temp level:d,scaledValueOfFirstFixedSurface,scaleFactorOfFirstFixedSurface '2.4 240 2'
grib_check_key_equals $temp level:d,scaledValueOfFirstFixedSurface,scaleFactorOfFirstFixedSurface '2.4 24 1'
# Use a parameter which has two levels
${tools_dir}/grib_set -s paramId=228086,topLevel=1.3,bottomLevel=5.4 $sample_g2 $temp
grib_check_key_equals $temp 'topLevel:d,bottomLevel:d' '1.3 5.4'
grib_check_key_equals $temp scaleFactorOfFirstFixedSurface,scaledValueOfFirstFixedSurface '2 130'
grib_check_key_equals $temp scaleFactorOfSecondFixedSurface,scaledValueOfSecondFixedSurface '2 540'
grib_check_key_equals $temp scaleFactorOfFirstFixedSurface,scaledValueOfFirstFixedSurface '1 13'
grib_check_key_equals $temp scaleFactorOfSecondFixedSurface,scaledValueOfSecondFixedSurface '1 54'
# GRIB-492
${tools_dir}/grib_set -s indicatorOfTypeOfLevel=110 $sample_g1 $temp
@ -86,8 +87,10 @@ res=`${tools_dir}/grib_get -p level:d $temp`
${tools_dir}/grib_set -s typeOfLevel=potentialVorticity,shortName=q,level=1500 $sample_g1 $temp
${tools_dir}/grib_set -s edition=2 $temp $temp2
grib_check_key_equals $temp2 'mars.levelist,level,typeOfLevel' '1500 1500 potentialVorticity'
grib_check_key_equals $temp2 'scaleFactorOfFirstFixedSurface,scaledValueOfFirstFixedSurface' '6 1500'
grib_check_key_equals $temp2 'scaleFactorOfFirstFixedSurface,scaledValueOfFirstFixedSurface' '9 1500'
${tools_dir}/grib_set -s level=1500 $temp2 $temp3
grib_check_key_equals $temp3 level 1500
${tools_dir}/grib_compare $temp2 $temp3
# GRIB-637 grib2 Potential vorticity surface
input=${data_dir}/tigge_pf_ecmwf.grib2
@ -121,4 +124,4 @@ for pid in $params; do
done
rm -f level.filter temp.level.good test.dump $temp $temp2
rm -f level.filter temp.level.good test.dump $temp $temp2 $temp3

View File

@ -181,5 +181,13 @@ for cval in -1 0 xx; do
done
# ECC-1562: Segmentation fault: Invalid orderby directive
set +e
${tools_dir}/grib_ls -B'shortName: asc' tigge_af_ecmwf.grib2 > $tempText 2>&1
status=$?
set -e
[ $status -ne 0 ]
grep -q "Invalid type for key=shortName" $tempText
# Clean up
rm -f $temp1 $temp2 $tempText $tempLog

View File

@ -47,24 +47,25 @@ done
# Various grid types
# ECC-1552: To be done later. Current behaviour is to return KeyNotFound
set +e
${tools_dir}/grib_get -p projString $grib2_sample > $tempText 2>&1
status=$?
set -e
[ $status -ne 0 ]
grep -q "Key/value not found" $tempText
# set +e
# ${tools_dir}/grib_get -p projString $grib2_sample > $tempText 2>&1
# status=$?
# set -e
# [ $status -ne 0 ]
# grep -q "Key/value not found" $tempText
rm -f $tempText
# ${tools_dir}/grib_get -p projString $grib2_sample > $tempText
# grep -q "proj=longlat +R=6367470" $tempText
${tools_dir}/grib_get -p projString $grib2_sample > $tempText
grep -q "+proj=longlat +datum=WGS84" $tempText
${tools_dir}/grib_get -p projString $ECCODES_SAMPLES_PATH/reduced_gg_pl_32_grib2.tmpl > $tempText
grep -q "+proj=longlat +datum=WGS84" $tempText
# ${tools_dir}/grib_get -p projString $ECCODES_SAMPLES_PATH/regular_ll_pl_grib2.tmpl > $tempText
# grep -q "proj=longlat +R=6371229" $tempText
# ${tools_dir}/grib_get -p projString $ECCODES_SAMPLES_PATH/regular_gg_ml_grib1.tmpl > $tempText
# grep -q "proj=longlat +R=6367470" $tempText
# ${tools_dir}/grib_get -p projString $ECCODES_SAMPLES_PATH/reduced_ll_sfc_grib1.tmpl > $tempText
# grep -q "proj=longlat +R=6367470" $tempText
# ${tools_dir}/grib_get -p projString $ECCODES_SAMPLES_PATH/reduced_gg_pl_32_grib2.tmpl > $tempText
# grep -q "proj=longlat +R=6371229" $tempText
${tools_dir}/grib_set -s gridType=lambert_azimuthal_equal_area $grib2_sample $tempGrib

View File

@ -116,5 +116,12 @@ status=$?
set -e
[ $status -ne 0 ]
# ECC-1081
# ---------
${tools_dir}/grib_set -s level=2 ${data_dir}/tigge/tigge_ecmf_pv_pt.grib $TEMP
grib_check_key_equals $TEMP level 2
# ${tools_dir}/grib_dump -O -p section_4 $TEMP
${tools_dir}/grib_compare ${data_dir}/tigge/tigge_ecmf_pv_pt.grib $TEMP
rm -f $TEMP

2784
tests/keys

File diff suppressed because it is too large Load Diff

View File

@ -439,13 +439,57 @@ static void test_dates()
Assert( !is_date_valid(2000, 5, 9, 0, 1, 60) );
Assert( !is_date_valid(2023, 2, 29, 0,0,0) );//Feb
}
void test_scale_factor_scaled_values()
{
int err =0;
int64_t value, factor;
const int64_t scaled_value_max = 4294967295; // usually 4 octets
const int64_t scale_factor_max = 255; // usually 1 octet
printf("Testing: scaled values and scale factors...\n");
err = compute_scaled_value_and_scale_factor(0, scaled_value_max, scale_factor_max, &value, &factor);
Assert(!err);
Assert(value == 0);
Assert(factor == 0);
err = compute_scaled_value_and_scale_factor(1, scaled_value_max, scale_factor_max, &value, &factor);
Assert(!err);
Assert(value == 1);
Assert(factor == 0);
err = compute_scaled_value_and_scale_factor(1.5, scaled_value_max, scale_factor_max, &value, &factor);
Assert(!err);
Assert(value == 15);
Assert(factor == 1);
err = compute_scaled_value_and_scale_factor(4.56, scaled_value_max, scale_factor_max, &value, &factor);
Assert(!err);
Assert(value == 456);
Assert(factor == 2);
err = compute_scaled_value_and_scale_factor(-0.003, scaled_value_max, scale_factor_max, &value, &factor);
Assert(!err);
Assert(value == -3);
Assert(factor == 3);
err = compute_scaled_value_and_scale_factor(145.889, scaled_value_max, scale_factor_max, &value, &factor);
Assert(!err);
Assert(value == 145889);
Assert(factor == 3);
err = compute_scaled_value_and_scale_factor(1111.00009, scaled_value_max, scale_factor_max, &value, &factor);
Assert(!err);
Assert(value == 111100009);
Assert(factor == 5);
}
int main(int argc, char** argv)
{
printf("Doing unit tests. ecCodes version = %ld\n", grib_get_api_version());
test_scale_factor_scaled_values();
test_dates();
test_logging_proc();
test_grib_binary_search();

View File

@ -91,15 +91,17 @@ ecbuild_add_executable( TARGET codes_bufr_filter
LIBS ecc_tools )
# grib1to2 script needs to be generated before installation
if( ECCODES_INSTALL_EXTRA_TOOLS )
ecbuild_info("ECCODES_INSTALL_EXTRA_TOOLS enabled")
# grib1to2 script needs to be generated before installation
configure_file( grib1to2.in grib1to2 )
install( FILES ${CMAKE_CURRENT_BINARY_DIR}/grib1to2
DESTINATION ${INSTALL_BIN_DIR}
PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
GROUP_EXECUTE GROUP_READ
WORLD_EXECUTE WORLD_READ )
else()
ecbuild_info("ECCODES_INSTALL_EXTRA_TOOLS disabled")
endif()
########################################