2021-03-07 12:46:25 +01:00
|
|
|
/**********************************************************************
|
2022-03-20 20:56:32 +01:00
|
|
|
* This file is used for testing random stuff without running the
|
2021-03-07 12:46:25 +01:00
|
|
|
* whole of SatDump, which comes in handy for debugging individual
|
|
|
|
|
* elements before putting them all together in modules...
|
2022-03-20 20:56:32 +01:00
|
|
|
*
|
|
|
|
|
* If you are an user, ignore this file which will not be built by
|
2021-05-12 21:16:53 +02:00
|
|
|
* default, and if you're a developper in need of doing stuff here...
|
2021-03-07 12:46:25 +01:00
|
|
|
* Go ahead!
|
2022-03-20 20:56:32 +01:00
|
|
|
*
|
2021-03-07 12:46:25 +01:00
|
|
|
* Don't judge the code you might see in there! :)
|
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
2022-03-28 11:51:13 +02:00
|
|
|
#include "logger.h"
|
2023-11-21 20:04:39 +01:00
|
|
|
#include <netcdf.h>
|
|
|
|
|
#include <mfhdf.h>
|
|
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
|
|
#include "common/utils.h"
|
|
|
|
|
|
2023-11-22 17:00:18 +01:00
|
|
|
#include "nlohmann/json.hpp"
|
|
|
|
|
#include "nlohmann/json_utils.h"
|
|
|
|
|
|
2023-11-21 20:04:39 +01:00
|
|
|
char *sanitize_string(char *str, bool sanitize)
|
|
|
|
|
{
|
|
|
|
|
char *new_str = NULL;
|
|
|
|
|
|
|
|
|
|
if (!str)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
new_str = strdup(str);
|
|
|
|
|
if (NULL == new_str)
|
|
|
|
|
{
|
|
|
|
|
printf("Out of memory!\n");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sanitize)
|
|
|
|
|
{
|
|
|
|
|
char *ptr = new_str;
|
|
|
|
|
|
|
|
|
|
/* Convert all non-alpha, non-numeric, non-hyphen, non-underscore
|
|
|
|
|
* characters to underscores
|
|
|
|
|
*/
|
|
|
|
|
for (; *ptr; ptr++)
|
|
|
|
|
if (!isalnum(*ptr) && *ptr != '_' && *ptr != '-')
|
|
|
|
|
*ptr = '_';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new_str;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string type_name(nc_type type)
|
|
|
|
|
{
|
|
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case NC_BYTE:
|
|
|
|
|
return "byte";
|
|
|
|
|
case NC_CHAR:
|
|
|
|
|
return "char";
|
|
|
|
|
case NC_SHORT:
|
|
|
|
|
return "short";
|
|
|
|
|
case NC_LONG:
|
|
|
|
|
return "long";
|
|
|
|
|
case NC_FLOAT:
|
|
|
|
|
return "float";
|
|
|
|
|
case NC_DOUBLE:
|
|
|
|
|
return "double";
|
|
|
|
|
default:
|
|
|
|
|
// error("type_name: bad type %d", type);
|
|
|
|
|
return "bogus";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *formats[] = {
|
|
|
|
|
"%d", /* bytes, shorts */
|
|
|
|
|
"%s", /* char arrays as strings */
|
|
|
|
|
"%ld", /* longs */
|
|
|
|
|
"%.7g ", /* floats */
|
|
|
|
|
"%.15g" /* doubles */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int upcorner(long *dims, int ndims, long *odom, long *add)
|
|
|
|
|
{
|
|
|
|
|
int id;
|
|
|
|
|
int ret = 1;
|
|
|
|
|
|
|
|
|
|
for (id = ndims - 1; id > 0; id--)
|
|
|
|
|
{
|
|
|
|
|
odom[id] += add[id];
|
|
|
|
|
if (odom[id] >= dims[id])
|
|
|
|
|
{
|
|
|
|
|
odom[id - 1]++;
|
|
|
|
|
odom[id] -= dims[id];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
odom[0] += add[0];
|
|
|
|
|
if (odom[0] >= dims[0])
|
|
|
|
|
ret = 0;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *get_fmt(int ncid, int varid, nc_type type)
|
|
|
|
|
{
|
|
|
|
|
// char *c_format_att = has_c_format_att(ncid, varid);
|
|
|
|
|
|
|
|
|
|
/* If C_format attribute exists, return it */
|
|
|
|
|
// if (c_format_att)
|
|
|
|
|
// return c_format_att;
|
|
|
|
|
|
|
|
|
|
/* Otherwise return sensible default. */
|
|
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case NC_BYTE:
|
|
|
|
|
return formats[0];
|
|
|
|
|
case NC_CHAR:
|
|
|
|
|
return formats[1];
|
|
|
|
|
case NC_SHORT:
|
|
|
|
|
return formats[0];
|
|
|
|
|
case NC_LONG:
|
|
|
|
|
return formats[2];
|
|
|
|
|
case NC_FLOAT:
|
|
|
|
|
return formats[3];
|
|
|
|
|
case NC_DOUBLE:
|
|
|
|
|
return formats[4];
|
|
|
|
|
default:
|
|
|
|
|
printf("pr_vals: bad type\n");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2023-11-22 17:00:18 +01:00
|
|
|
std::string dumpArray(T *vals_pr, nlohmann::json &json_output, char *fmt, int depth, long dim_sizes[], int &pos, int curr_dim = 0)
|
2023-11-21 20:04:39 +01:00
|
|
|
{
|
|
|
|
|
std::string final_decl;
|
|
|
|
|
final_decl += "{";
|
|
|
|
|
for (int i = 0; i < dim_sizes[curr_dim]; i++)
|
|
|
|
|
{
|
|
|
|
|
if (depth > 1)
|
2023-11-22 17:00:18 +01:00
|
|
|
final_decl += dumpArray(vals_pr, json_output[i], fmt, depth - 1, dim_sizes, pos, curr_dim + 1);
|
2023-11-21 20:04:39 +01:00
|
|
|
else
|
2023-11-22 17:00:18 +01:00
|
|
|
{
|
|
|
|
|
final_decl += svformat(fmt, vals_pr[pos]); // std::to_string(*(vals_pr++));
|
|
|
|
|
json_output[i] = vals_pr[pos++];
|
|
|
|
|
}
|
2023-11-21 20:04:39 +01:00
|
|
|
if (i + 1 < dim_sizes[curr_dim])
|
|
|
|
|
final_decl += ", ";
|
|
|
|
|
}
|
|
|
|
|
// logger->critical("POS %d - %d", depth, pos);
|
|
|
|
|
final_decl += "}";
|
|
|
|
|
return final_decl;
|
|
|
|
|
}
|
2023-09-07 08:37:08 +02:00
|
|
|
|
2023-11-13 15:41:02 +01:00
|
|
|
int main(int /*argc*/, char *argv[])
|
2023-11-13 01:28:14 +01:00
|
|
|
{
|
2023-11-13 15:41:02 +01:00
|
|
|
initLogger();
|
2023-11-19 16:22:39 -05:00
|
|
|
completeLoggerInit();
|
2023-10-11 00:54:06 +02:00
|
|
|
|
2023-11-22 17:00:18 +01:00
|
|
|
nlohmann::json json_output;
|
|
|
|
|
|
2023-11-21 20:04:39 +01:00
|
|
|
int ncid = ncopen(argv[1], NC_NOWRITE); /* netCDF id */
|
|
|
|
|
|
|
|
|
|
if (ncid == -1)
|
|
|
|
|
{
|
|
|
|
|
printf("ncopen failed on %s\n", argv[1]);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* get number of dimensions, number of variables, number of global
|
|
|
|
|
* atts, and dimension id of unlimited dimension, if any
|
|
|
|
|
*/
|
|
|
|
|
int ndims = 0;
|
|
|
|
|
int nvars = 0;
|
|
|
|
|
int ngatts = 0;
|
|
|
|
|
int xdimid = 0;
|
|
|
|
|
(void)ncinquire(ncid, &ndims, &nvars, &ngatts, &xdimid);
|
|
|
|
|
|
|
|
|
|
std::vector<std::pair<std::string, int>> all_dims;
|
|
|
|
|
|
2023-11-22 17:00:18 +01:00
|
|
|
std::vector<std::string> vals_json_intrusive;
|
|
|
|
|
|
2023-11-21 20:04:39 +01:00
|
|
|
if (ndims > 0)
|
|
|
|
|
{
|
|
|
|
|
for (int dimid = 0; dimid < ndims; dimid++)
|
|
|
|
|
{
|
|
|
|
|
char name[1000];
|
|
|
|
|
long dim_size = 0;
|
|
|
|
|
char *fixed_str = NULL;
|
|
|
|
|
|
|
|
|
|
if (ncdiminq(ncid, dimid, name, &dim_size) < 0)
|
|
|
|
|
fprintf(stderr, "Error calling ncdiminq on dimid = %d\n", dimid);
|
|
|
|
|
|
|
|
|
|
fixed_str = sanitize_string(name, true);
|
|
|
|
|
if (fixed_str == NULL)
|
|
|
|
|
{
|
|
|
|
|
(void)ncclose(ncid);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("#define %s %d\n", fixed_str, dim_size);
|
|
|
|
|
|
|
|
|
|
all_dims.push_back({std::string(fixed_str), dim_size});
|
|
|
|
|
|
|
|
|
|
free(fixed_str);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
|
|
printf("struct HDF4File {\n");
|
|
|
|
|
|
2023-11-22 17:00:18 +01:00
|
|
|
vals_json_intrusive.push_back("HDF4File");
|
|
|
|
|
|
2023-11-21 20:04:39 +01:00
|
|
|
/* get variable info, with variable attributes */
|
|
|
|
|
for (int varid = 0; varid < nvars; varid++)
|
|
|
|
|
{
|
|
|
|
|
char name[1000];
|
|
|
|
|
nc_type type;
|
|
|
|
|
int ndims = 0;
|
|
|
|
|
int dims[100];
|
|
|
|
|
int natts;
|
|
|
|
|
char *fixed_str = NULL;
|
|
|
|
|
|
|
|
|
|
if (ncvarinq(ncid, varid, name, &type, &ndims, dims, &natts) < 0)
|
|
|
|
|
fprintf(stderr, "Error calling ncvarinq on dimid = %d\n", varid);
|
|
|
|
|
|
|
|
|
|
fixed_str = sanitize_string(name, true);
|
|
|
|
|
if (fixed_str == NULL)
|
|
|
|
|
{
|
|
|
|
|
(void)ncclose(ncid);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf(" %s %s ", type_name(type).c_str(), fixed_str);
|
|
|
|
|
|
2023-11-22 17:00:18 +01:00
|
|
|
// if (ndims > 0)
|
|
|
|
|
// printf("[");
|
2023-11-21 20:04:39 +01:00
|
|
|
|
|
|
|
|
long vdims[100];
|
|
|
|
|
|
2023-11-22 17:00:18 +01:00
|
|
|
// std::string final_type_str = " ";
|
|
|
|
|
|
|
|
|
|
// for (int id = 0; id < ndims; id++)
|
|
|
|
|
// final_type_str += "std::array<";
|
|
|
|
|
|
|
|
|
|
int total_dim = 1;
|
|
|
|
|
|
2023-11-21 20:04:39 +01:00
|
|
|
for (int id = 0; id < ndims; id++)
|
|
|
|
|
{
|
|
|
|
|
char *fixed_dim = sanitize_string((char *)all_dims[dims[id]].first.c_str(), true);
|
|
|
|
|
vdims[id] = all_dims[dims[id]].second;
|
|
|
|
|
|
2023-11-22 17:00:18 +01:00
|
|
|
total_dim *= vdims[id];
|
|
|
|
|
|
2023-11-21 20:04:39 +01:00
|
|
|
if (fixed_dim == NULL)
|
|
|
|
|
{
|
|
|
|
|
(void)ncclose(ncid);
|
|
|
|
|
// free(fixed_var);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-22 17:00:18 +01:00
|
|
|
// if (id + 1 == ndims)
|
|
|
|
|
// final_type_str += type_name(type);
|
|
|
|
|
// final_type_str += "std::array< , " + std::string(fixed_dim )
|
|
|
|
|
|
|
|
|
|
// printf("%s%s", fixed_dim, id < ndims - 1 ? "][ " : "]");
|
2023-11-21 20:04:39 +01:00
|
|
|
free(fixed_dim);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-22 17:00:18 +01:00
|
|
|
printf("[%d]", total_dim);
|
|
|
|
|
vals_json_intrusive.push_back(std::string(fixed_str));
|
|
|
|
|
|
|
|
|
|
// for (int id = ndims - 1; id >= 0; id--)
|
|
|
|
|
// final_type_str += ", " + std::string(sanitize_string((char *)all_dims[dims[id]].first.c_str(), true)) + ">";
|
|
|
|
|
|
|
|
|
|
// final_type_str += " " + std::string(fixed_str);
|
|
|
|
|
|
|
|
|
|
// printf("%s", final_type_str.c_str());
|
|
|
|
|
|
2023-11-21 20:04:39 +01:00
|
|
|
std::vector<float> float_vals;
|
|
|
|
|
std::vector<short> short_vals;
|
|
|
|
|
std::vector<long> long_vals;
|
|
|
|
|
std::vector<char> byte_vals;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
long cor[H4_MAX_VAR_DIMS]; /* corner coordinates */
|
|
|
|
|
long edg[H4_MAX_VAR_DIMS]; /* edges of hypercube */
|
|
|
|
|
long add[H4_MAX_VAR_DIMS]; /* "odometer" increment to next "row" */
|
|
|
|
|
#define VALBUFSIZ 8192
|
|
|
|
|
double vals[VALBUFSIZ / sizeof(double)]; /* aligned buffer */
|
|
|
|
|
int gulp = VALBUFSIZ / nctypelen(type);
|
|
|
|
|
|
|
|
|
|
int id;
|
|
|
|
|
int ir;
|
|
|
|
|
long nels;
|
|
|
|
|
long ncols;
|
|
|
|
|
long nrows;
|
|
|
|
|
int vrank = ndims;
|
|
|
|
|
// char *fixed_var;
|
|
|
|
|
int ret = 0, err_code = 0;
|
|
|
|
|
|
|
|
|
|
/* printf format used to print each value */
|
|
|
|
|
// const char *fmt = get_fmt(ncid, varid, type);
|
|
|
|
|
|
|
|
|
|
nels = 1;
|
|
|
|
|
for (id = 0; id < vrank; id++)
|
|
|
|
|
{
|
|
|
|
|
cor[id] = 0;
|
|
|
|
|
edg[id] = 1;
|
|
|
|
|
nels *= vdims[id]; /* total number of values for variable */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (vrank <= 1)
|
|
|
|
|
{
|
|
|
|
|
// printf("\n %s = ", fixed_str);
|
|
|
|
|
// set_indent(strlen(fixed_var) + 4);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// printf("\n %s =\n ", fixed_str);
|
|
|
|
|
// set_indent(2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (vrank < 1)
|
|
|
|
|
{
|
|
|
|
|
ncols = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ncols = vdims[vrank - 1]; /* size of "row" along last dimension */
|
|
|
|
|
edg[vrank - 1] = vdims[vrank - 1];
|
|
|
|
|
for (id = 0; id < vrank; id++)
|
|
|
|
|
add[id] = 0;
|
|
|
|
|
if (vrank > 1)
|
|
|
|
|
add[vrank - 2] = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// printf("\nCOLS %d VRANK %d\n", ncols, vrank);
|
|
|
|
|
|
|
|
|
|
nrows = nels / ncols; /* number of "rows" */
|
|
|
|
|
|
|
|
|
|
for (ir = 0; ir < nrows; ir++)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* rather than just printing a whole row at once (which might exceed
|
|
|
|
|
* the capacity of MSDOS platforms, for example), we break each row
|
|
|
|
|
* into smaller chunks, if necessary.
|
|
|
|
|
*/
|
|
|
|
|
long corsav = 0;
|
|
|
|
|
long left = ncols;
|
|
|
|
|
bool lastrow;
|
|
|
|
|
|
|
|
|
|
lastrow = (ir == nrows - 1) ? true : false;
|
|
|
|
|
while (left > 0)
|
|
|
|
|
{
|
|
|
|
|
long toget = left < gulp ? left : gulp;
|
|
|
|
|
if (vrank > 0)
|
|
|
|
|
edg[vrank - 1] = toget;
|
|
|
|
|
|
|
|
|
|
/* ncvarget was casted to (void), thus ncdump misinformed users
|
|
|
|
|
that the reading succeeded even though the data was corrupted and
|
|
|
|
|
reading in fact failed (HDFFR-1468.) Now when ncvarget fails,
|
|
|
|
|
break out of the while loop and set error code to indicate this
|
|
|
|
|
failure. -BMR, 2015/01/19 */
|
|
|
|
|
ret = ncvarget(ncid, varid, cor, edg, (void *)vals);
|
|
|
|
|
if (ret == -1)
|
|
|
|
|
{
|
|
|
|
|
// err_code = ERR_READFAIL; /* to be returned to caller to
|
|
|
|
|
// indicate that ncvarget fails */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if (fsp->full_data_cmnts)
|
|
|
|
|
// {
|
|
|
|
|
// pr_cvals(vp, toget, fmt, left > toget, lastrow, (void *)vals, fsp, cor);
|
|
|
|
|
// }
|
|
|
|
|
// else
|
|
|
|
|
{
|
|
|
|
|
int len = toget;
|
|
|
|
|
for (int iel = 0; iel < len; iel++)
|
|
|
|
|
{
|
|
|
|
|
if (type == NC_FLOAT)
|
|
|
|
|
float_vals.push_back(((float *)vals)[iel]);
|
|
|
|
|
else if (type == NC_SHORT)
|
|
|
|
|
short_vals.push_back(((short *)vals)[iel]);
|
|
|
|
|
else if (type == NC_LONG)
|
|
|
|
|
long_vals.push_back(((long *)vals)[iel]);
|
|
|
|
|
else if (type == NC_BYTE)
|
|
|
|
|
byte_vals.push_back(((char *)vals)[iel]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
left -= toget;
|
|
|
|
|
if (vrank > 0)
|
|
|
|
|
cor[vrank - 1] += toget;
|
|
|
|
|
}
|
|
|
|
|
/* No failure occurs */
|
|
|
|
|
if (ret >= 0)
|
|
|
|
|
{
|
|
|
|
|
if (vrank > 0)
|
|
|
|
|
cor[vrank - 1] = corsav;
|
|
|
|
|
if (ir < nrows - 1)
|
|
|
|
|
if (!upcorner(vdims, ndims, cor, add))
|
|
|
|
|
printf("vardata: odometer overflowed!\n");
|
|
|
|
|
// set_indent(2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// free(fixed_var);
|
|
|
|
|
// return (err_code);
|
|
|
|
|
}
|
2023-10-29 21:37:02 +01:00
|
|
|
|
2023-11-21 20:04:39 +01:00
|
|
|
char *fmt = get_fmt(ncid, varid, type);
|
|
|
|
|
int pos = 0;
|
|
|
|
|
if (float_vals.size() > 0)
|
2023-11-22 17:00:18 +01:00
|
|
|
json_output[std::string(fixed_str)] = float_vals; // /*printf(" = %s",*/ dumpArray(float_vals.data(), json_output[std::string(fixed_str)], fmt, ndims, vdims, pos).c_str(); //);
|
2023-11-21 20:04:39 +01:00
|
|
|
else if (short_vals.size() > 0)
|
2023-11-22 17:00:18 +01:00
|
|
|
json_output[std::string(fixed_str)] = short_vals; // /*printf(" = %s",*/ dumpArray(short_vals.data(), json_output[std::string(fixed_str)], fmt, ndims, vdims, pos).c_str(); //);
|
2023-11-21 20:04:39 +01:00
|
|
|
else if (long_vals.size() > 0)
|
2023-11-22 17:00:18 +01:00
|
|
|
json_output[std::string(fixed_str)] = long_vals; // /*printf(" = %s",*/ dumpArray(long_vals.data(), json_output[std::string(fixed_str)], fmt, ndims, vdims, pos).c_str(); //);
|
2023-11-21 20:04:39 +01:00
|
|
|
else if (byte_vals.size() > 0)
|
2023-11-22 17:00:18 +01:00
|
|
|
json_output[std::string(fixed_str)] = byte_vals; // /*printf(" = %s",*/ dumpArray(byte_vals.data(), json_output[std::string(fixed_str)], fmt, ndims, vdims, pos).c_str(); //);
|
2023-11-13 01:28:14 +01:00
|
|
|
|
2023-11-21 20:04:39 +01:00
|
|
|
logger->critical("POS %d %d", float_vals.size(), pos);
|
2023-11-13 01:28:14 +01:00
|
|
|
|
2023-11-21 20:04:39 +01:00
|
|
|
printf(";\n");
|
2023-10-27 13:34:53 +02:00
|
|
|
|
2023-11-22 17:00:18 +01:00
|
|
|
saveCborFile(argv[2], json_output);
|
|
|
|
|
|
2023-11-21 20:04:39 +01:00
|
|
|
free(fixed_str);
|
|
|
|
|
}
|
2023-10-27 13:34:53 +02:00
|
|
|
|
2023-11-22 17:00:18 +01:00
|
|
|
printf("\n NLOHMANN_DEFINE_TYPE_INTRUSIVE(");
|
|
|
|
|
for (int v = 0; v < vals_json_intrusive.size(); v++)
|
|
|
|
|
{
|
|
|
|
|
if (vals_json_intrusive.size() - 1 == v)
|
|
|
|
|
printf("%s", vals_json_intrusive[v].c_str());
|
|
|
|
|
else
|
|
|
|
|
printf("%s, ", vals_json_intrusive[v].c_str());
|
|
|
|
|
if (v % 6 == 5)
|
|
|
|
|
printf("\n ");
|
|
|
|
|
}
|
|
|
|
|
printf(")\n");
|
|
|
|
|
|
2023-11-21 20:04:39 +01:00
|
|
|
printf("};\n");
|
|
|
|
|
}
|