From 8fa517c9ff8723a76449de6a11371bf00d3069ec Mon Sep 17 00:00:00 2001
From: rinkk <karsten.rink@ufz.de>
Date: Tue, 10 Sep 2019 12:47:48 +0200
Subject: [PATCH] added command line parameters

---
 .../Utils/FileConverter/NetCdfConverter.cpp   | 390 ++++++++++++++----
 1 file changed, 303 insertions(+), 87 deletions(-)

diff --git a/Applications/Utils/FileConverter/NetCdfConverter.cpp b/Applications/Utils/FileConverter/NetCdfConverter.cpp
index 741dc70e797..527369ef22e 100644
--- a/Applications/Utils/FileConverter/NetCdfConverter.cpp
+++ b/Applications/Utils/FileConverter/NetCdfConverter.cpp
@@ -47,20 +47,22 @@ void showErrorMessage(std::size_t error_id, std::size_t max = 0)
 {
     if (error_id == 0)
     {
-        ERR ("Input not valid.");
+        ERR("Input not valid.");
     }
     else if (error_id == 1)
     {
-        ERR ("Index not valid. Valid indices are in [0,%d].", max);
+        ERR("Index not valid. Valid indices are in [0,%d].", max);
     }
     else if (error_id == 2)
     {
         showErrorMessage(0);
-        std::cout << "Type \"info\" to display the available options again. \"exit\" will exit the programme.\n";
+        std::cout << "Type \"info\" to display the available options again. "
+                     "\"exit\" will exit the programme.\n";
     }
 }
 
-std::size_t parseInput(std::string const& request_str, std::size_t max_val, bool has_info = false)
+std::size_t parseInput(std::string const& request_str, std::size_t max_val,
+                       bool has_info = false)
 {
     while (true)
     {
@@ -97,14 +99,16 @@ NcVar getDimVar(NcFile const& dataset, NcVar const& var, std::size_t const dim)
 std::vector<std::string> showArrays(NcFile const& dataset)
 {
     std::size_t const n_vars(dataset.getDimCount());
-    std::cout << "The NetCDF file contains the following " << n_vars << " arrays:\n\n";
+    std::cout << "The NetCDF file contains the following " << n_vars
+              << " arrays:\n\n";
     std::cout << "\tIndex\tArray Name\t#Dimensions\n";
     std::cout << "-------------------------------------------\n";
     auto const& names = dataset.getVars();
     std::vector<std::string> var_names;
     for (auto [name, var] : names)
     {
-        std::cout << "\t" << var_names.size() << "\t" << name << "\t(" << var.getDimCount() << "D array)\n";
+        std::cout << "\t" << var_names.size() << "\t" << name << "\t("
+                  << var.getDimCount() << "D array)\n";
         var_names.push_back(name);
     }
     std::cout << "\n";
@@ -115,9 +119,10 @@ bool showArraysDims(NcVar const& var)
 {
     std::cout << "Data array \"" << var.getName()
               << "\" contains the following dimensions:\n";
-    std::size_t const n_dims (var.getDimCount());
-    for (std::size_t i=0; i<n_dims; ++i)
-        std::cout << "\t" << i << "\t" << var.getDim(i).getName() << "\t(" << var.getDim(i).getSize() << " values)\n";
+    std::size_t const n_dims(var.getDimCount());
+    for (std::size_t i = 0; i < n_dims; ++i)
+        std::cout << "\t" << i << "\t" << var.getDim(i).getName() << "\t("
+                  << var.getDim(i).getSize() << " values)\n";
     std::cout << "\n";
     return true;
 }
@@ -140,25 +145,27 @@ MathLib::Point3d getOrigin(NcFile const& dataset, NcVar const& var,
                            bool is_time_dep)
 {
     std::size_t const temp_offset = (is_time_dep) ? 1 : 0;
-    MathLib::Point3d origin(std::array<double, 3>{ {0, 0, 0}});
+    MathLib::Point3d origin(std::array<double, 3>{{0, 0, 0}});
     std::size_t const n_dims = var.getDimCount();
     for (std::size_t i = temp_offset; i < n_dims; ++i)
     {
         NcVar const& dim = getDimVar(dataset, var, dim_idx_map[i]);
         auto const bounds = getBoundaries(dim);
-        origin[i-temp_offset] = (bounds.first < bounds.second) ? bounds.first : bounds.second;
+        origin[i - temp_offset] =
+            (bounds.first < bounds.second) ? bounds.first : bounds.second;
     }
     return origin;
 }
 
-void flipRaster(std::vector<double>& data, std::size_t width, std::size_t height)
+void flipRaster(std::vector<double>& data, std::size_t width,
+                std::size_t height)
 {
-    std::size_t const length (data.size());
-    std::vector<double> tmp_vec (length);
-    for (std::size_t i=0; i<height; i++)
+    std::size_t const length(data.size());
+    std::vector<double> tmp_vec(length);
+    for (std::size_t i = 0; i < height; i++)
     {
         std::size_t const line_idx(length - (width * (i + 1)));
-        for (std::size_t j=0; j<width; j++)
+        for (std::size_t j = 0; j < width; j++)
         {
             tmp_vec.push_back(data[line_idx + j]);
         }
@@ -168,16 +175,18 @@ void flipRaster(std::vector<double>& data, std::size_t width, std::size_t height
 
 bool canConvert(NcVar const& var)
 {
-    bool ret (true);
+    bool ret(true);
     if (ret = (var.getDimCount() < 2))
-        ERR ("Only 2+ dimensional variables can be converted into OGS Meshes.\n");
+        ERR("Only 2+ dimensional variables can be converted into OGS "
+            "Meshes.\n");
     return !ret;
 }
 
 std::string arraySelectionLoop(NcFile const& dataset)
 {
     std::vector<std::string> const& names = showArrays(dataset);
-    std::size_t idx = parseInput("Enter data array index: ", dataset.getVarCount(), true);
+    std::size_t idx =
+        parseInput("Enter data array index: ", dataset.getVarCount(), true);
 
     if (idx == dataset.getVarCount() || !canConvert(dataset.getVar(names[idx])))
         return arraySelectionLoop(dataset);
@@ -185,19 +194,21 @@ std::string arraySelectionLoop(NcFile const& dataset)
     return names[idx];
 }
 
-bool dimensionSelectionLoop(NcVar const& var, std::array<std::size_t,4> &dim_idx_map)
+bool dimensionSelectionLoop(NcVar const& var,
+                            std::array<std::size_t, 4>& dim_idx_map)
 {
     showArraysDims(var);
     std::size_t const n_dims(var.getDimCount());
     dim_idx_map[0] = std::numeric_limits<std::size_t>::max();
-    bool is_time_dep (true);
+    bool is_time_dep(true);
 
     // get temporal dimension
     if (n_dims > 1)
     {
         std::string temp_str("");
         cout << "Is the parameter time-dependent?\n";
-        while (dim_idx_map[0] == std::numeric_limits<std::size_t>::max() && is_time_dep == true)
+        while (dim_idx_map[0] == std::numeric_limits<std::size_t>::max() &&
+               is_time_dep == true)
         {
             cout << "Enter ID for temporal dimension or \"c\" to continue: ";
             std::getline(std::cin, temp_str);
@@ -212,7 +223,7 @@ bool dimensionSelectionLoop(NcVar const& var, std::array<std::size_t,4> &dim_idx
                     dim_idx_map[0] = std::numeric_limits<std::size_t>::max();
                     continue;
                 }
-                if (dim_idx_map[0] > n_dims-1)
+                if (dim_idx_map[0] > n_dims - 1)
                 {
                     showErrorMessage(1, var.getDimCount() - 1);
                     dim_idx_map[0] = std::numeric_limits<std::size_t>::max();
@@ -225,11 +236,15 @@ bool dimensionSelectionLoop(NcVar const& var, std::array<std::size_t,4> &dim_idx
 
     // get spatial dimension(s)
     std::size_t const start_idx = (is_time_dep) ? 1 : 0;
-    for (std::size_t i=start_idx; i<n_dims; ++i)
+    std::array<std::string, 4> dim_comment{
+        "(x / longitude)", "(y / latitude)", "(z / height / depth)",
+        "[Error: 4-dimensional non-temporal arrays are not supported]"};
+    for (std::size_t i = start_idx; i < n_dims; ++i)
     {
         dim_idx_map[i] = std::numeric_limits<std::size_t>::max();
 
-        std::string request_str ("Enter ID for dimension " + std::to_string(i) + ": ");
+        std::string request_str("Enter ID for dimension " + std::to_string(i) +
+                                " " + dim_comment[i - start_idx] + ": ");
         std::size_t idx = parseInput(request_str, var.getDimCount(), true);
 
         if (idx == var.getDimCount())
@@ -244,7 +259,9 @@ bool dimensionSelectionLoop(NcVar const& var, std::array<std::size_t,4> &dim_idx
     return is_time_dep;
 }
 
-std::pair<std::size_t, std::size_t> timestepSelectionLoop(NcFile const& dataset, NcVar const& var, std::size_t dim_idx)
+std::pair<std::size_t, std::size_t> timestepSelectionLoop(NcFile const& dataset,
+                                                          NcVar const& var,
+                                                          std::size_t dim_idx)
 {
     NcVar const& dim_var = getDimVar(dataset, var, dim_idx);
     std::size_t const n_time_steps = var.getDim(dim_idx).getSize();
@@ -252,15 +269,17 @@ std::pair<std::size_t, std::size_t> timestepSelectionLoop(NcFile const& dataset,
         std::numeric_limits<std::size_t>::max(),
         std::numeric_limits<std::size_t>::max());
     std::cout << "\nThe dataset contains " << n_time_steps << " time steps.\n";
-    bounds.first = parseInput("Specify first time step to export: ", n_time_steps, false);
+    bounds.first =
+        parseInput("Specify first time step to export: ", n_time_steps, false);
     while (bounds.first > bounds.second || bounds.second > n_time_steps)
-        bounds.second = parseInput("Specify last time step to export: ", n_time_steps, false);
+        bounds.second = parseInput(
+            "Specify last time step to export: ", n_time_steps, false);
     return bounds;
 }
 
 MeshLib::MeshElemType elemSelectionLoop(std::size_t const dim)
 {
-    if (dim ==1)
+    if (dim == 1)
         return MeshLib::MeshElemType::LINE;
 
     MeshLib::MeshElemType t = MeshLib::MeshElemType::INVALID;
@@ -268,15 +287,16 @@ MeshLib::MeshElemType elemSelectionLoop(std::size_t const dim)
     {
         std::cout << "\nSelect element type for result, choose ";
 
-        if (dim==2) std::cout << "(t)riangle or (q)uadliteral: ";
-        if (dim==3) std::cout << "(p)rism or (h)exahedron: ";
-        std::string type ("");
+        if (dim == 2)
+            std::cout << "(t)riangle or (q)uadliteral: ";
+        if (dim == 3)
+            std::cout << "(p)rism or (h)exahedron: ";
+        std::string type("");
         std::getline(std::cin, type);
         checkExit(type);
-        if (dim==2)
+        if (dim == 2)
         {
-            if (type != "t" && type != "q" &&
-                type != "tri" && type != "quad" &&
+            if (type != "t" && type != "q" && type != "tri" && type != "quad" &&
                 type != "triangle" && type != "quatliteral")
                 continue;
             if (type == "t" || type == "tri" || type == "triangle")
@@ -285,11 +305,10 @@ MeshLib::MeshElemType elemSelectionLoop(std::size_t const dim)
                 return MeshLib::MeshElemType::QUAD;
         }
 
-        if (dim==3)
+        if (dim == 3)
         {
-            if (type != "p" && type != "h" &&
-                type != "prism" && type != "hex" &&
-                type != "hexahedron")
+            if (type != "p" && type != "h" && type != "prism" &&
+                type != "hex" && type != "hexahedron")
                 continue;
             if (type == "p" || type == "prism")
                 return MeshLib::MeshElemType::PRISM;
@@ -300,20 +319,24 @@ MeshLib::MeshElemType elemSelectionLoop(std::size_t const dim)
     return t;
 }
 
-bool multFilesSelectionLoop(std::pair<std::size_t, std::size_t> const& time_bounds)
+bool multFilesSelectionLoop(
+    std::pair<std::size_t, std::size_t> const& time_bounds)
 {
     std::size_t n_time_steps(time_bounds.second - time_bounds.first + 1);
-    std::cout << "\nThe selection includes " << n_time_steps << " time steps.\n";
-    std::cout << "0. Save data in " << n_time_steps << " mesh files with one scalar array each.\n";
-    std::cout << "1. Save data in one mesh file with " << n_time_steps << " scalar arrays.\n";
+    std::cout << "\nThe selection includes " << n_time_steps
+              << " time steps.\n";
+    std::cout << "0. Save data in " << n_time_steps
+              << " mesh files with one scalar array each.\n";
+    std::cout << "1. Save data in one mesh file with " << n_time_steps
+              << " scalar arrays.\n";
     std::size_t ret = parseInput("Select preferred method: ", 2, false);
     return (ret == 0) ? true : false;
 }
 
 std::string getIterationString(std::size_t i, std::size_t max)
 {
-    std::size_t const max_length (std::to_string(max).length());
-    std::string const current_str (std::to_string(i));
+    std::size_t const max_length(std::to_string(max).length());
+    std::string const current_str(std::to_string(i));
     return std::string(max_length - current_str.length(), '0') + current_str;
 }
 
@@ -321,7 +344,8 @@ double getResolution(NcFile const& dataset, NcVar const& var)
 {
     std::size_t dim_idx = var.getDimCount() - 1;
     auto const bounds = getBoundaries(getDimVar(dataset, var, dim_idx));
-    return fabs(bounds.second - bounds.first) / static_cast<double>(var.getDim(dim_idx).getSize());
+    return fabs(bounds.second - bounds.first) /
+           static_cast<double>(var.getDim(dim_idx).getSize());
 }
 
 GeoLib::RasterHeader createRasterHeader(
@@ -333,11 +357,18 @@ GeoLib::RasterHeader createRasterHeader(
     double const res = getResolution(dataset, var);
     std::size_t n_dims = var.getDimCount();
     std::size_t temp_offset = (is_time_dep) ? 1 : 0;
-    std::size_t z_length = (n_dims - temp_offset == 3) ? length[dim_idx_map.back()] : 1;
-    return {length[dim_idx_map[0 + temp_offset]], length[dim_idx_map[1 + temp_offset]], z_length, origin, res, -9999};
+    std::size_t z_length =
+        (n_dims - temp_offset == 3) ? length[dim_idx_map.back()] : 1;
+    return {length[dim_idx_map[0 + temp_offset]],
+            length[dim_idx_map[1 + temp_offset]],
+            z_length,
+            origin,
+            res,
+            -9999};
 }
 
-std::size_t getLength(NcVar const& var, bool const is_time_dep, std::vector<std::size_t> &length)
+std::size_t getLength(NcVar const& var, bool const is_time_dep,
+                      std::vector<std::size_t>& length)
 {
     std::size_t const temp_offset = (is_time_dep) ? 1 : 0;
     std::size_t const n_dims = (var.getDimCount());
@@ -356,7 +387,7 @@ std::vector<double> getData(NcFile const& dataset, NcVar const& var,
                             std::size_t const time_step,
                             std::vector<std::size_t> const& length)
 {
-    std::size_t const n_dims (var.getDimCount());
+    std::size_t const n_dims(var.getDimCount());
     std::vector<std::size_t> offset(n_dims, 0);
     offset[0] = time_step;
     std::vector<double> data_vec(total_length, 0);
@@ -364,7 +395,8 @@ std::vector<double> getData(NcFile const& dataset, NcVar const& var,
     std::replace_if(data_vec.begin(), data_vec.end(),
                     [](double& x) { return x <= -9999; }, -9999);
 
-    // reverse lines in vertical direction if the original file has its origin in the northwest corner
+    // reverse lines in vertical direction if the original file has its origin
+    // in the northwest corner
     NcVar const& dim_var = getDimVar(dataset, var, n_dims - 1);
     auto const bounds = getBoundaries(dim_var);
     if (bounds.first > bounds.second)
@@ -372,7 +404,88 @@ std::vector<double> getData(NcFile const& dataset, NcVar const& var,
     return data_vec;
 }
 
-int main (int argc, char* argv[])
+bool assignDimParams(NcVar const& var,
+                     std::array<std::size_t, 4>& dim_idx_map,
+                     TCLAP::ValueArg<std::size_t>& arg_dim_time,
+                     TCLAP::ValueArg<std::size_t>& arg_dim1,
+                     TCLAP::ValueArg<std::size_t>& arg_dim2,
+                     TCLAP::ValueArg<std::size_t>& arg_dim3)
+{
+    if (arg_dim3.isSet() && !arg_dim2.isSet())
+    {
+        ERR("Parameter for dim2 is not set. Ignoring dimension parameters.");
+        return false;
+    }
+    if (!arg_dim1.isSet() || !arg_dim2.isSet())
+    {
+        ERR("dim1 and dim2 need to be set for extracting mesh.");
+        return false;
+    }
+
+    std::size_t const n_dims = var.getDimCount();
+    if (arg_dim_time.getValue() >= n_dims || arg_dim1.getValue() >= n_dims ||
+        arg_dim2.getValue() >= n_dims || arg_dim3.getValue() >= n_dims)
+    {
+        ERR("Maximum allowed dimension for variable \"%s\" is %d.", var.getName().c_str(), n_dims-1);
+        return false;
+    }
+
+    bool is_time_dep = arg_dim_time.isSet();
+    if (is_time_dep)
+        dim_idx_map[0] = arg_dim_time.getValue();
+    std::size_t const temp_offset = (is_time_dep) ? 1 : 0;
+    dim_idx_map[0 + temp_offset] = arg_dim1.getValue();
+    dim_idx_map[1 + temp_offset] = arg_dim2.getValue();
+    if (n_dims == (3 + temp_offset))
+        dim_idx_map[2 + temp_offset] = arg_dim3.getValue();
+
+    return true;
+}
+
+std::pair<std::size_t, std::size_t> assignTimeBounds(NcVar const& var,
+                     TCLAP::ValueArg<std::size_t>& arg_time_start,
+                     TCLAP::ValueArg<std::size_t>& arg_time_end)
+{
+    auto const bounds = getBoundaries(var);
+    if (arg_time_start.getValue() > bounds.second)
+    {
+        ERR("Start time step larger than total number of time steps. Resetting to 0.");
+        arg_time_start.reset();
+    }
+
+    if (!arg_time_end.isSet())
+        return {arg_time_start.getValue(), arg_time_start.getValue()};
+
+    if (arg_time_end.getValue() > bounds.second)
+    {
+        ERR("End time step larger than total number of time steps. Resetting to starting time step");
+        return {arg_time_start.getValue(), arg_time_start.getValue()};
+    }
+
+    if (arg_time_end.getValue() < arg_time_start.getValue())
+    {
+        ERR("End time step larger than starting time step. Swapping values");
+        return {arg_time_end.getValue(), arg_time_start.getValue()};
+    }
+
+    return {arg_time_start.getValue(), arg_time_end.getValue()};
+}
+
+MeshLib::MeshElemType assignElemType(TCLAP::ValueArg<std::string>& arg_elem_type)
+{
+    if (arg_elem_type.getValue() == "tri")
+        return MeshLib::MeshElemType::TRIANGLE;
+    if (arg_elem_type.getValue() == "quad")
+        return MeshLib::MeshElemType::QUAD;
+    if (arg_elem_type.getValue() == "prism")
+        return MeshLib::MeshElemType::PRISM;
+    if (arg_elem_type.getValue() == "hex")
+        return MeshLib::MeshElemType::HEXAHEDRON;
+    // this should never happen
+    return MeshLib::MeshElemType::INVALID;
+}
+
+int main(int argc, char* argv[])
 {
     ApplicationsLib::LogogSetup logog_setup;
 
@@ -385,17 +498,74 @@ int main (int argc, char* argv[])
             "(http://www.opengeosys.org)",
         ' ', GitInfoLib::GitInfo::ogs_version);
 
-    TCLAP::ValueArg<std::string> input("i", "input-file",
-                                       "the NetCDF input file", true,
-                                       "", "the NetCDF input file");
-    cmd.add(input);
-    TCLAP::ValueArg<std::string> output("o", "output-file",
-                                        "the OGS mesh output file", true,
-                                        "", "the OGS mesh output file");
-    cmd.add(output);
+    std::vector<std::string> allowed_elems{"tri", "quad", "prism", "hex"};
+    TCLAP::ValuesConstraint<std::string> allowed_elem_vals(allowed_elems);
+    TCLAP::ValueArg<std::string> arg_elem_type(
+        "e", "elem-type", "the element type used in the resulting OGS mesh",
+        false, "", &allowed_elem_vals);
+    cmd.add(arg_elem_type);
+
+    TCLAP::SwitchArg arg_single_file(
+        "", "single-file",
+        "if set, all time steps will be written to a single mesh file (with "
+        "one scalar array per time step)");
+    cmd.add(arg_single_file);
+
+    TCLAP::ValueArg<std::size_t> arg_time_end(
+        "", "timestep-last",
+        "last time step to be extracted (only for time-dependent variables!)",
+        false, 0, "integer specifying index of time step");
+    cmd.add(arg_time_end);
+
+    TCLAP::ValueArg<std::size_t> arg_time_start(
+        "", "timestep-first",
+        "first time step to be extracted (only for time-dependent variables!)",
+        false, 0, "integer specifying index of time step");
+    cmd.add(arg_time_start);
+
+    std::vector<std::size_t> allowed_dims{0, 1, 2, 3};
+    TCLAP::ValuesConstraint<std::size_t> allowed_dim_vals(allowed_dims);
+    TCLAP::ValueArg<std::size_t> arg_dim3(
+        "", "dim3",
+        "index of third dimension (z/height/depth) for the selected variable",
+        false, 0, &allowed_dim_vals);
+    cmd.add(arg_dim3);
+
+    TCLAP::ValueArg<std::size_t> arg_dim2(
+        "", "dim2",
+        "index of second dimension (y/latitude) for the selected "
+        "variable",
+        false, 0, &allowed_dim_vals);
+    cmd.add(arg_dim2);
+
+    TCLAP::ValueArg<std::size_t> arg_dim1(
+        "", "dim1",
+        "index of first dimension (x/longitude) for the selected variable",
+        false, 0, &allowed_dim_vals);
+    cmd.add(arg_dim1);
+
+    TCLAP::ValueArg<std::size_t> arg_dim_time(
+        "t", "time",
+        "index of the time-dependent dimension for the selected variable",
+        false, 0, &allowed_dim_vals);
+    cmd.add(arg_dim_time);
+
+    TCLAP::ValueArg<std::string> arg_varname(
+        "v", "var", "variable from the netCDF file", false, "",
+        "string containing the variable name");
+    cmd.add(arg_varname);
+
+    TCLAP::ValueArg<std::string> arg_output(
+        "o", "output", "the OGS mesh output file", true, "",
+        "string containing the path and file name");
+    cmd.add(arg_output);
+    TCLAP::ValueArg<std::string> arg_input(
+        "i", "input", "the netCDF input file", true, "",
+        "string containing the path and file name");
+    cmd.add(arg_input);
     cmd.parse(argc, argv);
 
-    NcFile dataset(input.getValue().c_str(), NcFile::read);
+    NcFile dataset(arg_input.getValue().c_str(), NcFile::read);
 
     if (dataset.isNull())
     {
@@ -404,23 +574,54 @@ int main (int argc, char* argv[])
     }
 
     std::cout << "OpenGeoSys NetCDF Converter\n";
-    std::cout << "File " << input.getValue() << " loaded. Press ENTER to display available data arrays.\n";
-    std::cin.ignore();
-    std::string output_name (output.getValue());
+    if (!arg_varname.isSet())
+    {
+        std::cout << "File " << arg_input.getValue()
+                  << " loaded. Press ENTER to display available data arrays.\n";
+        std::cin.ignore();
+    }
 
-    std::string const& var_name = arraySelectionLoop(dataset);
-    NcVar& var = dataset.getVar(var_name);
+    std::string const output_name(arg_output.getValue());
+    std::string const& var_name = (arg_varname.isSet())
+                                      ? arg_varname.getValue()
+                                      : arraySelectionLoop(dataset);
+    NcVar const& var = dataset.getVar(var_name);
+    if (var.isNull())
+    {
+        ERR("Variable \"%s\" not found in file.", arg_varname.getValue().c_str());
+        return EXIT_FAILURE;
+    }
 
     std::array<std::size_t, 4> dim_idx_map;
-    bool const is_time_dep = dimensionSelectionLoop(var, dim_idx_map);
+    bool is_time_dep (false);
+    if (arg_dim1.isSet() && arg_dim2.isSet())
+    {
+        is_time_dep = arg_dim_time.isSet();
+        if (!assignDimParams(var, dim_idx_map, arg_dim_time, arg_dim1, arg_dim2, arg_dim3))
+            return EXIT_FAILURE;
+    }
+    else
+    {
+        is_time_dep = dimensionSelectionLoop(var, dim_idx_map);
+    }
 
-    std::pair<std::size_t, std::size_t> time_bounds(0,0);
+    std::pair<std::size_t, std::size_t> time_bounds(0, 0);
     if (is_time_dep)
-        time_bounds = timestepSelectionLoop(dataset, var, dim_idx_map[0]);
+        time_bounds = (arg_time_start.isSet())
+                ? assignTimeBounds(getDimVar(dataset, var, dim_idx_map[0]),
+                                   arg_time_start, arg_time_end)
+                : timestepSelectionLoop(dataset, var, dim_idx_map[0]);
 
-    bool mult_files (false);
-    if (is_time_dep && time_bounds.first != time_bounds.second)
-        mult_files = multFilesSelectionLoop(time_bounds);
+    bool use_single_file(true);
+    if (arg_time_start.isSet())
+    {
+        use_single_file = arg_single_file.isSet();
+    }
+    else
+    {
+        if (is_time_dep && time_bounds.first != time_bounds.second)
+            use_single_file = multFilesSelectionLoop(time_bounds);
+    }
 
     std::unique_ptr<MeshLib::Mesh> mesh;
     std::size_t const temp_offset = (is_time_dep) ? 1 : 0;
@@ -428,38 +629,53 @@ int main (int argc, char* argv[])
     std::vector<std::size_t> length;
     std::size_t const array_length = getLength(var, is_time_dep, length);
 
-    MeshLib::MeshElemType const meshElemType = elemSelectionLoop(n_dims - temp_offset);
-    for (std::size_t i=time_bounds.first; i<=time_bounds.second; ++i)
+    MeshLib::MeshElemType const meshElemType = (arg_elem_type.isSet())
+        ? assignElemType(arg_elem_type)
+        : elemSelectionLoop(n_dims - temp_offset);
+    for (std::size_t i = time_bounds.first; i <= time_bounds.second; ++i)
     {
         std::cout << "Converting time step " << i << "...\n";
-        std::vector<double> data_vec = getData(dataset, var, array_length, i, length);
+        std::vector<double> data_vec =
+            getData(dataset, var, array_length, i, length);
 
         GeoLib::RasterHeader header =
             createRasterHeader(dataset, var, dim_idx_map, length, is_time_dep);
-        MeshLib::UseIntensityAs const useIntensity = MeshLib::UseIntensityAs::DATAVECTOR;
-        if (mult_files)
+        MeshLib::UseIntensityAs const useIntensity =
+            MeshLib::UseIntensityAs::DATAVECTOR;
+        if (!use_single_file)
         {
-            mesh.reset(MeshLib::RasterToMesh::convert(data_vec.data(), header, meshElemType, useIntensity, var.getName()));
-            std::string const output_file_name (BaseLib::dropFileExtension(output_name) + getIterationString(i, time_bounds.second) + ".vtu");
+            mesh.reset(MeshLib::RasterToMesh::convert(
+                data_vec.data(), header, meshElemType, useIntensity,
+                var.getName()));
+            std::string const output_file_name(
+                BaseLib::dropFileExtension(output_name) +
+                getIterationString(i, time_bounds.second) + ".vtu");
             MeshLib::IO::VtuInterface vtu(mesh.get());
             vtu.writeToFile(output_file_name);
         }
         else
         {
-            std::string array_name (var.getName());
+            std::string array_name(var.getName());
             if (time_bounds.first != time_bounds.second)
                 array_name.append(getIterationString(i, time_bounds.second));
-            if (i==time_bounds.first) // create persistent mesh
-                mesh.reset(MeshLib::RasterToMesh::convert(data_vec.data(), header, meshElemType, useIntensity, array_name));
-            else // copy array to mesh
+            if (i == time_bounds.first)  // create persistent mesh
+                mesh.reset(MeshLib::RasterToMesh::convert(
+                    data_vec.data(), header, meshElemType, useIntensity,
+                    array_name));
+            else  // copy array to mesh
             {
-                std::unique_ptr<MeshLib::Mesh> temp (MeshLib::RasterToMesh::convert(data_vec.data(), header, meshElemType, useIntensity, array_name));
-                MeshLib::PropertyVector<double> const*const vec = temp->getProperties().getPropertyVector<double>(array_name);
+                std::unique_ptr<MeshLib::Mesh> temp(
+                    MeshLib::RasterToMesh::convert(data_vec.data(), header,
+                                                   meshElemType, useIntensity,
+                                                   array_name));
+                MeshLib::PropertyVector<double> const* const vec =
+                    temp->getProperties().getPropertyVector<double>(array_name);
                 if (vec == nullptr)
                     return EXIT_FAILURE;
-                MeshLib::addPropertyToMesh<double>(*mesh, array_name, MeshLib::MeshItemType::Cell, 1, *vec);
+                MeshLib::addPropertyToMesh<double>(
+                    *mesh, array_name, MeshLib::MeshItemType::Cell, 1, *vec);
             }
-            if (i==time_bounds.second)
+            if (i == time_bounds.second)
             {
                 MeshLib::IO::VtuInterface vtu(mesh.get());
                 vtu.writeToFile(output_name);
-- 
GitLab