mirror of https://github.com/ecmwf/eccodes.git
Merge branch 'feature/grid_complex_encoding' of github.com:ecmwf/eccodes into feature/grid_complex_encoding
This commit is contained in:
commit
9c6ad56c01
|
@ -1 +1 @@
|
|||
-DENABLE_EXTRA_TESTS=1
|
||||
-DENABLE_EXTRA_TESTS=1 -DECCODES_INSTALL_EXTRA_TOOLS=1
|
||||
|
|
|
@ -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_
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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
|
|
@ -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"
|
|
@ -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"
|
|
@ -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";
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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;}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -410,13 +410,20 @@ static int grib_concept_apply(grib_accessor* a, const char* name)
|
|||
grib_get_string(h, "centre", centre_s, ¢re_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 */
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.");
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
13082
src/grib_hash_keys.cc
13082
src/grib_hash_keys.cc
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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"
|
||||
# -----------------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
2784
tests/keys
File diff suppressed because it is too large
Load Diff
|
@ -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();
|
||||
|
|
|
@ -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()
|
||||
########################################
|
||||
|
||||
|
|
Loading…
Reference in New Issue