ECC-1424: Allow accessor from_scale_factor_scaled_value to operate on an array of scaled values

This commit is contained in:
Shahram Najm 2022-07-11 15:57:30 +01:00
parent 40d1680a4f
commit 8d227a71c6
2 changed files with 104 additions and 35 deletions

View File

@ -21,6 +21,7 @@
CLASS = accessor
SUPER = grib_accessor_class_double
IMPLEMENTS = unpack_double;pack_double;is_missing
IMPLEMENTS = value_count
IMPLEMENTS = init
MEMBERS=const char* scaleFactor
MEMBERS=const char* scaledValue
@ -41,6 +42,7 @@ or edit "accessor.class" and rerun ./make_class.pl
static int is_missing(grib_accessor*);
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 value_count(grib_accessor*, long*);
static void init(grib_accessor*, const long, grib_arguments*);
static void init_class(grib_accessor_class*);
@ -68,7 +70,7 @@ static grib_accessor_class _grib_accessor_class_from_scale_factor_scaled_value =
0, /* describes himself */
0, /* get length of section */
0, /* get length of string */
0, /* get number of values */
&value_count, /* get number of values */
0, /* get number of bytes */
0, /* get offset to bytes */
0, /* get native type */
@ -109,7 +111,6 @@ static void init_class(grib_accessor_class* c)
c->dump = (*(c->super))->dump;
c->next_offset = (*(c->super))->next_offset;
c->string_length = (*(c->super))->string_length;
c->value_count = (*(c->super))->value_count;
c->byte_count = (*(c->super))->byte_count;
c->byte_offset = (*(c->super))->byte_offset;
c->get_native_type = (*(c->super))->get_native_type;
@ -147,7 +148,7 @@ 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++);
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; */
@ -244,7 +245,7 @@ static int get_scaled_value_and_scale_factor_algorithm2(
*ret_factor = factor;
*ret_value = value;
return GRIB_SUCCESS;
}
@ -312,45 +313,75 @@ static int pack_double(grib_accessor* a, const double* val, size_t* len)
static int unpack_double(grib_accessor* a, double* val, size_t* len)
{
grib_accessor_from_scale_factor_scaled_value* self = (grib_accessor_from_scale_factor_scaled_value*)a;
int err = 0;
long scaleFactor = 0;
long scaledValue = 0;
grib_handle* hand = grib_handle_of_accessor(a);
int err = 0;
long scaleFactor = 0, scaledValue = 0;
grib_handle* hand = grib_handle_of_accessor(a);
grib_context* c = a->context;
size_t vsize = 0;
if ((err = grib_get_long_internal(hand, self->scaleFactor, &scaleFactor)) != GRIB_SUCCESS)
return err;
if ((err = grib_get_long_internal(hand, self->scaledValue, &scaledValue)) != GRIB_SUCCESS)
if ((err = grib_get_size(hand, self->scaledValue, &vsize)) != GRIB_SUCCESS)
return err;
if (grib_is_missing(hand, self->scaledValue, &err) && err == GRIB_SUCCESS) {
*val = GRIB_MISSING_DOUBLE;
*len = 1;
return GRIB_SUCCESS;
} else {
/* 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);
scaleFactor = 0;
if (vsize == 1) {
if ((err = grib_get_long_internal(hand, self->scaledValue, &scaledValue)) != GRIB_SUCCESS)
return err;
if (grib_is_missing(hand, self->scaledValue, &err) && err == GRIB_SUCCESS) {
*val = GRIB_MISSING_DOUBLE;
*len = 1;
return GRIB_SUCCESS;
} else {
/* 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);
scaleFactor = 0;
}
}
}
*val = scaledValue;
*val = scaledValue;
/* The formula is:
* real_value = scaled_value / pow(10, scale_factor)
*/
while (scaleFactor < 0) {
*val *= 10;
scaleFactor++;
}
while (scaleFactor > 0) {
*val /= 10;
scaleFactor--;
}
/* The formula is:
* real_value = scaled_value / pow(10, scale_factor)
*/
while (scaleFactor < 0) {
*val *= 10;
scaleFactor++;
}
while (scaleFactor > 0) {
*val /= 10;
scaleFactor--;
}
if (err == GRIB_SUCCESS)
*len = 1;
if (err == GRIB_SUCCESS)
*len = 1;
} else {
size_t i;
long* lvalues = (long*)grib_context_malloc(c, vsize * sizeof(long));
if (!lvalues)
return GRIB_OUT_OF_MEMORY;
if ((err = grib_get_long_array_internal(hand, self->scaledValue, lvalues, &vsize)) != GRIB_SUCCESS) {
grib_context_free(c, lvalues);
return err;
}
for (i = 0; i < vsize; i++) {
long sf = scaleFactor;
val[i] = lvalues[i];
while (sf < 0) {
val[i] *= 10;
sf++;
}
while (sf > 0) {
val[i] /= 10;
sf--;
}
}
*len = vsize;
grib_context_free(c, lvalues);
}
return err;
}
@ -370,3 +401,16 @@ static int is_missing(grib_accessor* a)
return ((scaleFactor == GRIB_MISSING_LONG) || (scaledValue == GRIB_MISSING_LONG));
}
static int value_count(grib_accessor* a, long* len)
{
grib_accessor_from_scale_factor_scaled_value* self = (grib_accessor_from_scale_factor_scaled_value*)a;
int err = 0;
grib_handle* hand = grib_handle_of_accessor(a);
size_t vsize;
if ((err = grib_get_size(hand, self->scaledValue, &vsize)) != GRIB_SUCCESS)
return err;
*len = (long)vsize;
return GRIB_SUCCESS;
}

View File

@ -14,6 +14,8 @@ REDIRECT=/dev/null
label="grib_filter_test"
tempFilt="temp.$label.filt"
tempGrib="temp.$label.grib"
tempOut="temp.$label.txt"
tempRef="temp.$label.ref"
if [ -f ${data_dir}/geavg.t12z.pgrbaf108 ]; then
tmpdata=grib_api.$$.grib
@ -217,6 +219,29 @@ grib_check_key_equals $tempGrib scaleFactorOfFirstFixedSurface MISSING
grib_check_key_equals $tempGrib scaledValueOfFirstFixedSurface MISSING
echo "Test from_scale_factor_scaled_value"
# -----------------------------------------
input="${samp_dir}/reduced_gg_pl_32_grib2.tmpl"
cat >$tempFilt <<EOF
meta pl_scaled from_scale_factor_scaled_value(one, pl);
print "pl_scaled=[pl_scaled%.2f]";
EOF
${tools_dir}/grib_filter $tempFilt $input > $tempOut
cat $tempOut
cat >$tempRef <<EOF
pl_scaled=2.00 2.70 3.60 4.00 4.50 5.00 6.00 6.40
7.20 7.50 8.00 9.00 9.00 9.60 10.00 10.80
10.80 12.00 12.00 12.00 12.80 12.80 12.80 12.80
12.80 12.80 12.80 12.80 12.80 12.80 12.80 12.80
12.80 12.80 12.80 12.80 12.80 12.80 12.80 12.80
12.80 12.80 12.80 12.80 12.00 12.00 12.00 10.80
10.80 10.00 9.60 9.00 9.00 8.00 7.50 7.20
6.40 6.00 5.00 4.50 4.00 3.60 2.70 2.00
EOF
diff $tempRef $tempOut
# Clean up
rm -f $tempGrib $tempFilt
rm -f $tempGrib $tempFilt $tempOut $tempRef
rm -f ${data_dir}/formatint.rules ${data_dir}/binop.rules