Michael Uleysky
3 years ago
11 changed files with 1146 additions and 0 deletions
@ -0,0 +1,191 @@
|
||||
--- |
||||
Language: Cpp |
||||
AccessModifierOffset: 0 |
||||
AlignAfterOpenBracket: Align |
||||
AlignArrayOfStructures: Right |
||||
AlignConsecutiveMacros: Consecutive |
||||
AlignConsecutiveAssignments: Consecutive |
||||
AlignConsecutiveBitFields: Consecutive |
||||
AlignConsecutiveDeclarations: Consecutive |
||||
AlignEscapedNewlines: Right |
||||
AlignOperands: Align |
||||
AlignTrailingComments: true |
||||
AllowAllArgumentsOnNextLine: true |
||||
AllowAllParametersOfDeclarationOnNextLine: true |
||||
AllowShortEnumsOnASingleLine: true |
||||
AllowShortBlocksOnASingleLine: Always |
||||
AllowShortCaseLabelsOnASingleLine: true |
||||
AllowShortFunctionsOnASingleLine: All |
||||
AllowShortLambdasOnASingleLine: All |
||||
AllowShortIfStatementsOnASingleLine: WithoutElse |
||||
AllowShortLoopsOnASingleLine: true |
||||
AlwaysBreakAfterDefinitionReturnType: None |
||||
AlwaysBreakAfterReturnType: None |
||||
AlwaysBreakBeforeMultilineStrings: false |
||||
AlwaysBreakTemplateDeclarations: MultiLine |
||||
AttributeMacros: |
||||
- __capability |
||||
BinPackArguments: true |
||||
BinPackParameters: true |
||||
BraceWrapping: |
||||
AfterCaseLabel: true |
||||
AfterClass: true |
||||
AfterControlStatement: Always |
||||
AfterEnum: true |
||||
AfterFunction: true |
||||
AfterNamespace: true |
||||
AfterObjCDeclaration: true |
||||
AfterStruct: true |
||||
AfterUnion: true |
||||
AfterExternBlock: true |
||||
BeforeCatch: true |
||||
BeforeElse: true |
||||
BeforeLambdaBody: true |
||||
BeforeWhile: false |
||||
IndentBraces: false |
||||
SplitEmptyFunction: true |
||||
SplitEmptyRecord: true |
||||
SplitEmptyNamespace: true |
||||
BreakBeforeBinaryOperators: None |
||||
BreakBeforeConceptDeclarations: true |
||||
BreakBeforeBraces: Custom |
||||
BreakBeforeInheritanceComma: false |
||||
BreakInheritanceList: AfterColon |
||||
BreakBeforeTernaryOperators: true |
||||
BreakConstructorInitializersBeforeComma: false |
||||
BreakConstructorInitializers: AfterColon |
||||
BreakAfterJavaFieldAnnotations: false |
||||
BreakStringLiterals: true |
||||
ColumnLimit: 180 |
||||
CommentPragmas: '^ IWYU pragma:' |
||||
QualifierAlignment: Leave |
||||
CompactNamespaces: false |
||||
ConstructorInitializerIndentWidth: 4 |
||||
ContinuationIndentWidth: 4 |
||||
Cpp11BracedListStyle: true |
||||
DeriveLineEnding: false |
||||
DerivePointerAlignment: false |
||||
DisableFormat: false |
||||
EmptyLineAfterAccessModifier: Never |
||||
EmptyLineBeforeAccessModifier: LogicalBlock |
||||
ExperimentalAutoDetectBinPacking: false |
||||
PackConstructorInitializers: NextLine |
||||
BasedOnStyle: '' |
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false |
||||
AllowAllConstructorInitializersOnNextLine: true |
||||
FixNamespaceComments: true |
||||
ForEachMacros: |
||||
- foreach |
||||
- Q_FOREACH |
||||
- BOOST_FOREACH |
||||
IfMacros: |
||||
- KJ_IF_MAYBE |
||||
IncludeBlocks: Preserve |
||||
IncludeCategories: |
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/' |
||||
Priority: 2 |
||||
SortPriority: 0 |
||||
CaseSensitive: false |
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)' |
||||
Priority: 3 |
||||
SortPriority: 0 |
||||
CaseSensitive: false |
||||
- Regex: '.*' |
||||
Priority: 1 |
||||
SortPriority: 0 |
||||
CaseSensitive: false |
||||
IncludeIsMainRegex: '(Test)?$' |
||||
IncludeIsMainSourceRegex: '' |
||||
IndentAccessModifiers: false |
||||
IndentCaseLabels: false |
||||
IndentCaseBlocks: false |
||||
IndentGotoLabels: false |
||||
IndentPPDirectives: None |
||||
IndentExternBlock: Indent |
||||
IndentRequires: false |
||||
IndentWidth: 1 |
||||
IndentWrappedFunctionNames: false |
||||
InsertTrailingCommas: None |
||||
JavaScriptQuotes: Leave |
||||
JavaScriptWrapImports: true |
||||
KeepEmptyLinesAtTheStartOfBlocks: true |
||||
LambdaBodyIndentation: Signature |
||||
MacroBlockBegin: '' |
||||
MacroBlockEnd: '' |
||||
MaxEmptyLinesToKeep: 1 |
||||
NamespaceIndentation: None |
||||
ObjCBinPackProtocolList: Auto |
||||
ObjCBlockIndentWidth: 2 |
||||
ObjCBreakBeforeNestedBlockParam: true |
||||
ObjCSpaceAfterProperty: false |
||||
ObjCSpaceBeforeProtocolList: true |
||||
PenaltyBreakAssignment: 2 |
||||
PenaltyBreakBeforeFirstCallParameter: 19 |
||||
PenaltyBreakComment: 300 |
||||
PenaltyBreakFirstLessLess: 120 |
||||
PenaltyBreakOpenParenthesis: 0 |
||||
PenaltyBreakString: 1000 |
||||
PenaltyBreakTemplateDeclaration: 10 |
||||
PenaltyExcessCharacter: 1000000 |
||||
PenaltyReturnTypeOnItsOwnLine: 120 |
||||
PenaltyIndentedWhitespace: 0 |
||||
PointerAlignment: Left |
||||
PPIndentWidth: -1 |
||||
ReferenceAlignment: Pointer |
||||
ReflowComments: false |
||||
RemoveBracesLLVM: false |
||||
SeparateDefinitionBlocks: Leave |
||||
ShortNamespaceLines: 1 |
||||
SortIncludes: CaseSensitive |
||||
SortJavaStaticImport: Before |
||||
SortUsingDeclarations: true |
||||
SpaceAfterCStyleCast: false |
||||
SpaceAfterLogicalNot: false |
||||
SpaceAfterTemplateKeyword: false |
||||
SpaceBeforeAssignmentOperators: true |
||||
SpaceBeforeCaseColon: false |
||||
SpaceBeforeCpp11BracedList: false |
||||
SpaceBeforeCtorInitializerColon: false |
||||
SpaceBeforeInheritanceColon: false |
||||
SpaceBeforeParens: Never |
||||
SpaceBeforeParensOptions: |
||||
AfterControlStatements: false |
||||
AfterForeachMacros: false |
||||
AfterFunctionDefinitionName: false |
||||
AfterFunctionDeclarationName: false |
||||
AfterIfMacros: false |
||||
AfterOverloadedOperator: false |
||||
BeforeNonEmptyParentheses: false |
||||
SpaceAroundPointerQualifiers: Default |
||||
SpaceBeforeRangeBasedForLoopColon: false |
||||
SpaceInEmptyBlock: false |
||||
SpaceInEmptyParentheses: false |
||||
SpacesBeforeTrailingComments: 1 |
||||
SpacesInAngles: Never |
||||
SpacesInConditionalStatement: false |
||||
SpacesInContainerLiterals: true |
||||
SpacesInCStyleCastParentheses: false |
||||
SpacesInLineCommentPrefix: |
||||
Minimum: 1 |
||||
Maximum: -1 |
||||
SpacesInParentheses: false |
||||
SpacesInSquareBrackets: false |
||||
SpaceBeforeSquareBrackets: false |
||||
BitFieldColonSpacing: None |
||||
Standard: Latest |
||||
StatementAttributeLikeMacros: |
||||
- Q_EMIT |
||||
StatementMacros: |
||||
- Q_UNUSED |
||||
- QT_REQUIRE_VERSION |
||||
TabWidth: 8 |
||||
UseCRLF: false |
||||
UseTab: Never |
||||
WhitespaceSensitiveMacros: |
||||
- STRINGIZE |
||||
- PP_STRINGIZE |
||||
- BOOST_PP_STRINGIZE |
||||
- NS_SWIFT_NAME |
||||
- CF_SWIFT_NAME |
||||
... |
||||
|
@ -0,0 +1,92 @@
|
||||
cmake_minimum_required(VERSION 3.23) |
||||
|
||||
# Make sure the user doesn't play dirty with symlinks |
||||
get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH) |
||||
get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH) |
||||
|
||||
# Disallow in-source builds |
||||
if(${srcdir} STREQUAL ${bindir}) |
||||
message(FATAL_ERROR "In-source builds are not allowed." |
||||
" Please create a directory and run cmake from there, passing the path" |
||||
" to this source directory as the last argument. This process created" |
||||
" the file `CMakeCache.txt' and the directory `CMakeFiles' in ${srcdir}." |
||||
" Please remove them.") |
||||
endif() |
||||
|
||||
project(odm CXX) |
||||
|
||||
if(NOT CMAKE_BUILD_TYPE) |
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel" FORCE) |
||||
endif() |
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/" CACHE INTERNAL "Location of our custom CMake modules." FORCE) |
||||
|
||||
include_directories(include) |
||||
|
||||
# Checking compiler options |
||||
set(default_options -Wall) |
||||
set(linker_options -Wall) |
||||
include(CheckCXXCompilerFlag) |
||||
set(saved_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) |
||||
# C++20 is required |
||||
CHECK_CXX_COMPILER_FLAG(-std=c++20 COMPILER_SUPPORTS_CXX20) |
||||
if(COMPILER_SUPPORTS_CXX20) |
||||
set(default_options ${default_options} -std=c++20) |
||||
else() |
||||
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++20 support. Please use a different C++ compiler.") |
||||
endif() |
||||
# Link time optimization check |
||||
set(CMAKE_REQUIRED_FLAGS -flto) |
||||
CHECK_CXX_COMPILER_FLAG(-flto COMPILER_SUPPORTS_FLTO) |
||||
if(COMPILER_SUPPORTS_FLTO AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug") |
||||
set(default_options ${default_options} -flto) |
||||
set(linker_options ${linker_options} -flto) |
||||
endif() |
||||
unset(CMAKE_REQUIRED_FLAGS) |
||||
# Clang can use lto only with gold linker |
||||
if(NOT COMPILER_SUPPORTS_FLTO) |
||||
set(CMAKE_REQUIRED_FLAGS -flto\ -fuse-ld=gold) |
||||
CHECK_CXX_COMPILER_FLAG(-flto\ -fuse-ld=gold COMPILER_SUPPORTS_FLTO_GOLD) |
||||
if(COMPILER_SUPPORTS_FLTO_GOLD AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug") |
||||
set(default_options ${default_options} -flto) |
||||
set(linker_options ${linker_options} -flto\ -fuse-ld=gold) |
||||
endif() |
||||
unset(CMAKE_REQUIRED_FLAGS) |
||||
endif() |
||||
# Dwarf-4 support check |
||||
set(CMAKE_REQUIRED_FLAGS -gdwarf-4) |
||||
CHECK_CXX_COMPILER_FLAG(-gdwarf-4 COMPILER_SUPPORTS_DWARF4) |
||||
if(COMPILER_SUPPORTS_DWARF4 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")) |
||||
set(default_options ${default_options} -gdwarf-4) |
||||
set(linker_options ${linker_options} -gdwarf-4) |
||||
endif() |
||||
unset(CMAKE_REQUIRED_FLAGS) |
||||
# -ipo flag check (Intel compiler link time optimization) |
||||
set(CMAKE_REQUIRED_FLAGS -ipo) |
||||
CHECK_CXX_COMPILER_FLAG(-ipo COMPILER_SUPPORTS_IPO) |
||||
if(COMPILER_SUPPORTS_IPO AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug") |
||||
set(default_options ${default_options} -ipo) |
||||
set(linker_options ${linker_options} -ipo) |
||||
endif() |
||||
unset(CMAKE_REQUIRED_FLAGS) |
||||
# Default hidden visibility check |
||||
set(CMAKE_REQUIRED_FLAGS -fvisibility=hidden) |
||||
CHECK_CXX_COMPILER_FLAG(-fvisibility=hidden COMPILER_SUPPORTS_HIDDEN) |
||||
if(COMPILER_SUPPORTS_HIDDEN) |
||||
set(default_options ${default_options} -fvisibility=hidden) |
||||
set(linker_options ${linker_options} -fvisibility=hidden) |
||||
endif() |
||||
unset(CMAKE_REQUIRED_FLAGS) |
||||
# Export dynamic. Required as modules mast call functions from main programm |
||||
set(CMAKE_REQUIRED_FLAGS -Wl,--export-dynamic) |
||||
CHECK_CXX_COMPILER_FLAG(-Wl,--export-dynamic COMPILER_SUPPORTS_EXPORTDYNAMIC) |
||||
if(COMPILER_SUPPORTS_EXPORTDYNAMIC) |
||||
set(linker_options ${linker_options} -Wl,--export-dynamic) |
||||
else() |
||||
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no support of --export-dynamic. Please use a different C++ compiler.") |
||||
endif() |
||||
unset(CMAKE_REQUIRED_FLAGS) |
||||
add_compile_options(${default_options}) |
||||
set(CMAKE_REQUIRED_FLAGS ${saved_CMAKE_REQUIRED_FLAGS}) |
||||
|
||||
add_subdirectory(src) |
@ -0,0 +1,312 @@
|
||||
#include "DataAdapters/ncfilealt.h" |
||||
#include "mdatetime.h" |
||||
#include "simple2ddata.h" |
||||
#include "specfunc.h" |
||||
#include "vartype.h" |
||||
#include <regex.h> |
||||
#include <stdlib.h> |
||||
#include <sys/types.h> |
||||
|
||||
#if !defined(M__NEMO) |
||||
#define M__NEMO |
||||
|
||||
using michlib::Ceil; |
||||
using michlib::Floor; |
||||
using michlib::int2; |
||||
using michlib::MDateTime; |
||||
using michlib::NCFileA; |
||||
using michlib::ToGeoDomainNeg; |
||||
|
||||
class NEMOData |
||||
{ |
||||
NCFileA nc, nct, ncs; |
||||
size_t xb, yb, xe, ye, layer; |
||||
std::vector<real> depths; |
||||
std::vector<MDateTime> times; |
||||
size_t nx; |
||||
MString title; |
||||
|
||||
class EnvVar |
||||
{ |
||||
MString name, oldvalue; |
||||
bool activated, saved; |
||||
|
||||
public: |
||||
EnvVar(): activated(false) {} |
||||
~EnvVar() { Deactivate(); } |
||||
|
||||
void Activate(const MString& var, const MString& val) |
||||
{ |
||||
if(activated) Deactivate(); |
||||
name = var; |
||||
char* curval = getenv(name.Buf()); |
||||
if(nullptr == curval) |
||||
saved = false; |
||||
else |
||||
{ |
||||
oldvalue = curval; |
||||
saved = true; |
||||
} |
||||
setenv(name.Buf(), val.Buf(), 1); |
||||
} |
||||
void Deactivate() |
||||
{ |
||||
if(!activated) return; |
||||
if(saved) |
||||
setenv(name.Buf(), oldvalue.Buf(), 1); |
||||
else |
||||
unsetenv(name.Buf()); |
||||
activated = false; |
||||
} |
||||
}; |
||||
|
||||
EnvVar proxy; |
||||
|
||||
public: |
||||
using Data = Simple2DData; |
||||
|
||||
Data ReadVar(const NCFileA& f, const MString& name, size_t i) const |
||||
{ |
||||
using DataType = int2; |
||||
constexpr DataType fill = -32767; |
||||
real unitmul = 1.0; |
||||
|
||||
auto offset = f.A<double>(name, "add_offset"); |
||||
auto scale = f.A<double>(name, "scale_factor"); |
||||
if(!offset || !scale) return Data(); |
||||
|
||||
auto unit = f.A<MString>(name, "units"); |
||||
if(unit && unit.Get() == "m s-1") unitmul = 100.0; |
||||
|
||||
Data data((xb < xe) ? (xe - xb + 1) : (nx + xe - xb + 1), ye - yb + 1, Lonb(), Latb()); |
||||
|
||||
if(xb < xe) |
||||
{ |
||||
auto var = f.V<DataType>(name, {"longitude", xb, xe - xb + 1}, {"latitude", yb, ye - yb + 1}, {"time", i, 1}, {"depth", layer, 1}); |
||||
if(!var) return Data(); |
||||
if(var.DimLen(0) != data.Nx() || var.DimLen(1) != data.Ny()) return Data(); |
||||
|
||||
for(size_t ix = 0; ix < var.DimLen(0); ix++) |
||||
for(size_t iy = 0; iy < var.DimLen(1); iy++) |
||||
{ |
||||
DataType v = var(ix, iy); |
||||
data(ix, iy) = (v == fill) ? Data::Fillval() : ((v * scale + offset) * unitmul); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
auto var1 = f.V<DataType>(name, {"longitude", xb}, {"latitude", yb, ye - yb + 1}, {"time", i, 1}, {"depth", layer, 1}); |
||||
auto var2 = f.V<DataType>(name, {"longitude", 0, xe + 1}, {"latitude", yb, ye - yb + 1}, {"time", i, 1}, {"depth", layer, 1}); |
||||
if(!(var1 && var2)) return Data(); |
||||
if((var1.DimLen(0) + var2.DimLen(0)) != data.Nx() || var1.DimLen(1) != data.Ny() || var2.DimLen(1) != data.Ny()) return Data(); |
||||
for(size_t ix = 0; ix < var1.DimLen(0); ix++) |
||||
for(size_t iy = 0; iy < var1.DimLen(1); iy++) |
||||
{ |
||||
DataType v = var1(ix, iy); |
||||
data(ix, iy) = (v == fill) ? Data::Fillval() : ((v * scale + offset) * unitmul); |
||||
} |
||||
for(size_t ix = 0; ix < var2.DimLen(0); ix++) |
||||
for(size_t iy = 0; iy < var2.DimLen(1); iy++) |
||||
{ |
||||
DataType v = var2(ix, iy); |
||||
data(ix + var1.DimLen(0), iy) = (v == fill) ? Data::Fillval() : ((v * scale + offset) * unitmul); |
||||
} |
||||
} |
||||
return data; |
||||
} |
||||
|
||||
Data ReadVar(const NCFileA& f, const MString& name, const std::vector<size_t>& tindex) const |
||||
{ |
||||
Data out; |
||||
if(tindex.size() == 0) return out; |
||||
|
||||
std::vector<size_t> count; |
||||
for(size_t i = 0; i < tindex.size(); i++) |
||||
{ |
||||
Data dat = ReadVar(f, name, tindex[i]); |
||||
if(!dat) return Data(); |
||||
out.Add(dat, count); |
||||
} |
||||
out.Div(count); |
||||
return out; |
||||
} |
||||
|
||||
public: |
||||
NEMOData() = default; |
||||
|
||||
// TODO: RetVal
|
||||
bool Open(const MString& type, const MString& cred, const MString& proxyurl = "") |
||||
{ |
||||
if(proxyurl.Exist()) proxy.Activate("all_proxy", proxyurl); |
||||
MString url, urlt, urls; |
||||
if(type == "DT") |
||||
{ |
||||
url = "https://" + cred + "@my.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy_my_0.083_P1D-m"; |
||||
title = "NEMO Delayed time, daily mean"; |
||||
} |
||||
if(type == "NRT") |
||||
{ |
||||
url = "https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/global-analysis-forecast-phy-001-024"; |
||||
title = "NEMO Near-real time, daily mean"; |
||||
} |
||||
if(type == "NRT6") |
||||
{ |
||||
url = "https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/global-analysis-forecast-phy-001-024-3dinst-uovo"; |
||||
urlt = "https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/global-analysis-forecast-phy-001-024-3dinst-thetao"; |
||||
urls = "https://" + cred + "@nrt.cmems-du.eu/thredds/dodsC/global-analysis-forecast-phy-001-024-3dinst-so"; |
||||
title = "NEMO Near-real time, 6h resolution"; |
||||
} |
||||
nc.Reset(url); |
||||
if(!nc) return false; |
||||
|
||||
{ |
||||
auto nx_ = nc.D("longitude"); |
||||
if(!nx_) |
||||
{ |
||||
nc.Reset(); |
||||
return false; |
||||
} |
||||
nx = nx_; |
||||
} |
||||
|
||||
if(urlt.Exist()) |
||||
{ |
||||
nct.Reset(urlt); |
||||
if(!nct) |
||||
{ |
||||
nc.Reset(); |
||||
return false; |
||||
} |
||||
} |
||||
if(urls.Exist()) |
||||
{ |
||||
ncs.Reset(urls); |
||||
if(!ncs) |
||||
{ |
||||
nc.Reset(); |
||||
nct.Reset(); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
auto rdepths = nc.V<float>("depth"); |
||||
if(!rdepths) |
||||
{ |
||||
nc.Reset(); |
||||
nct.Reset(); |
||||
ncs.Reset(); |
||||
return false; |
||||
} |
||||
depths.resize(rdepths.DimLen(0)); |
||||
for(size_t i = 0; i < depths.size(); i++) depths[i] = rdepths(i); |
||||
|
||||
auto timeD = nc.V<double>("time"); |
||||
auto timeF = nc.V<float>("time"); |
||||
if(!(timeD || timeF)) |
||||
{ |
||||
nc.Reset(); |
||||
nct.Reset(); |
||||
ncs.Reset(); |
||||
return false; |
||||
} |
||||
MDateTime refdate("1950-01-01"); |
||||
timeD ? times.resize(timeD.DimLen(0)) : times.resize(timeF.DimLen(0)); |
||||
for(size_t i = 0; i < times.size(); i++) times[i] = refdate + static_cast<time_t>(timeD ? timeD(i) : timeF(i)) * 3600; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
MString Info() const |
||||
{ |
||||
MString d; |
||||
for(size_t i = 0; i < NDepths(); i++) d += MString(" ") + "(" + i + " " + Depth(i) + ")"; |
||||
|
||||
// clang-format off
|
||||
return |
||||
"NEMO dataset title: " + Title() + "\n" + |
||||
" Begin date: " + Time(0).ToString() + "\n" + |
||||
" End date: " + Time(NTimes()-1).ToString() + "\n" + |
||||
" Time step: " + Timestep() + " seconds\n" + |
||||
" Time moments: " + NTimes() + "\n" + |
||||
" Depths:" + d; |
||||
// clang-format on
|
||||
} |
||||
|
||||
bool SetRegion(real lonbin, real lonein, real latb, real late, real depth) |
||||
{ |
||||
if(!nc) return false; |
||||
real lonb = ToGeoDomainNeg(lonbin), lone = ToGeoDomainNeg(lonein); |
||||
|
||||
size_t xb_, xe_, yb_, ye_, layer_ = 0; |
||||
|
||||
yb_ = static_cast<size_t>(Floor((latb + 80.0) * 12.0)); |
||||
ye_ = static_cast<size_t>(Ceil((late + 80.0) * 12.0)); |
||||
if(ye_ > 2040) ye_ = 2040; |
||||
if(yb_ >= ye_) return false; |
||||
|
||||
xb_ = static_cast<size_t>(Floor((lonb + 180.0) * 12.0)); |
||||
xe_ = static_cast<size_t>(Ceil((lone + 180.0) * 12.0)); |
||||
if(xb_ == xe_) return false; |
||||
|
||||
if(depth < 0.0 || depth > depths.back()) |
||||
layer_ = (depth < 0.0) ? 0 : (depths.size() - 1); |
||||
else |
||||
for(size_t i = 0; i < depths.size() - 1; i++) |
||||
{ |
||||
if(depth >= depths[i] && depth <= depths[i + 1]) |
||||
{ |
||||
layer_ = (depth - depths[i] <= depths[i + 1] - depth) ? i : (i + 1); |
||||
break; |
||||
} |
||||
} |
||||
xb = xb_; |
||||
xe = xe_; |
||||
yb = yb_; |
||||
ye = ye_; |
||||
layer = layer_; |
||||
return true; |
||||
} |
||||
|
||||
real Lonb() const { return nc ? (-180.0 + xb / 12.0) : -1000.0; } |
||||
real Lone() const { return nc ? (-180.0 + xe / 12.0) : -1000.0; } |
||||
real Latb() const { return nc ? (-80.0 + yb / 12.0) : -1000.0; } |
||||
real Late() const { return nc ? (-80.0 + ye / 12.0) : -1000.0; } |
||||
size_t Xb() const { return nc ? xb : 0; } |
||||
size_t Xe() const { return nc ? xe : 0; } |
||||
size_t Yb() const { return nc ? yb : 0; } |
||||
size_t Ye() const { return nc ? ye : 0; } |
||||
size_t Nx() const { return nc ? ((xb < xe) ? (xe - xb + 1) : (nx + xe - xb + 1)) : 0; } |
||||
size_t Ny() const { return nc ? (ye - yb + 1) : 0; } |
||||
real Depth(size_t l) const { return nc ? depths[l] : -1000.0; } |
||||
real Depth() const { return Depth(layer); } |
||||
size_t Layer() const { return layer; } |
||||
time_t Timestep() const { return nc ? (times[1] - times[0]) : 0; } |
||||
MDateTime Time(size_t i) const |
||||
{ |
||||
if((!nc) || i >= times.size()) return MDateTime(); |
||||
return times[i]; |
||||
} |
||||
|
||||
size_t NDepths() const { return depths.size(); } |
||||
size_t NTimes() const { return times.size(); } |
||||
|
||||
template<vartype::Vartype vt> Data Read(size_t it) const = delete; |
||||
|
||||
template<vartype::Vartype vt> Data Read(const std::vector<size_t>& tindex) const = delete; |
||||
|
||||
MString Title() const { return title; } |
||||
|
||||
static real Fillval() { return Data::Fillval(); } |
||||
}; |
||||
|
||||
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::U>(size_t it) const { return ReadVar(nc, "uo", it); } |
||||
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::V>(size_t it) const { return ReadVar(nc, "vo", it); } |
||||
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::TEMP>(size_t it) const { return ReadVar(nct ? nct : nc, "thetao", it); } |
||||
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::SAL>(size_t it) const { return ReadVar(ncs ? ncs : nc, "so", it); } |
||||
|
||||
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::U>(const std::vector<size_t>& tindex) const { return ReadVar(nc, "uo", tindex); } |
||||
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::V>(const std::vector<size_t>& tindex) const { return ReadVar(nc, "vo", tindex); } |
||||
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::TEMP>(const std::vector<size_t>& tindex) const { return ReadVar(nct ? nct : nc, "thetao", tindex); } |
||||
template<> inline NEMOData::Data NEMOData::Read<vartype::Vartype::SAL>(const std::vector<size_t>& tindex) const { return ReadVar(ncs ? ncs : nc, "so", tindex); } |
||||
|
||||
#endif |
@ -0,0 +1,32 @@
|
||||
#include "comdefs.h" |
||||
|
||||
#if !defined(M__BASEDATA) |
||||
#define M__BASEDATA |
||||
|
||||
using michlib::real; |
||||
|
||||
class BaseData |
||||
{ |
||||
protected: |
||||
static constexpr real fillval = 1.0e10; |
||||
std::vector<real> data; |
||||
|
||||
BaseData() = default; |
||||
|
||||
BaseData(size_t n): data(n) {} |
||||
|
||||
public: |
||||
const real& V(size_t i) const { return data[i]; } |
||||
real& V(size_t i) { return data[i]; } |
||||
|
||||
const real& operator()(size_t i) const { return data[i]; } |
||||
real& operator()(size_t i) { return data[i]; } |
||||
|
||||
size_t N() const { return data.size(); } |
||||
|
||||
static real Fillval() { return fillval; } |
||||
|
||||
explicit operator bool() const { return data.size() != 0; } |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,70 @@
|
||||
#include "BFileW.h" |
||||
#include "NEMO.h" |
||||
#include "tindexes.h" |
||||
|
||||
#if !defined(M__ODM) |
||||
#define M__ODM |
||||
|
||||
using michlib::BFileW; |
||||
using michlib::errmessage; |
||||
using michlib::GPL; |
||||
using michlib::message; |
||||
using michlib::SList; |
||||
|
||||
using DataVariants = std::variant<NEMOData>; |
||||
using CLArgs = std::map<MString, MString>; |
||||
|
||||
class Data: public DataVariants |
||||
{ |
||||
template<class D> static bool WriteData(BFileW& fw, const D& data) |
||||
{ |
||||
for(size_t i = 0; i < data.N(); i++) |
||||
{ |
||||
fw.Write(data.Lon(i)); |
||||
fw.Write(data.Lat(i)); |
||||
fw.Write(data(i) == data.Fillval() ? NAN : data(i)); |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
public: |
||||
Data() = default; |
||||
|
||||
Data(DataVariants&& d): DataVariants(std::move(d)) {} |
||||
|
||||
auto Time(size_t it) const |
||||
{ |
||||
return std::visit( |
||||
[it = it](const auto& arg) -> auto{ return arg.Time(it); }, *this); |
||||
} |
||||
auto NTimes() const |
||||
{ |
||||
return std::visit( |
||||
[](const auto& arg) -> auto{ return arg.NTimes(); }, *this); |
||||
} |
||||
|
||||
bool Write(BFileW& fw, VarType vt, const std::vector<size_t>& tindexes) const |
||||
{ |
||||
return std::visit( |
||||
[&fw = fw, vt = vt, &ti = tindexes](const auto& d) -> bool |
||||
{ |
||||
using T = std::decay_t<decltype(d)>; |
||||
|
||||
return std::visit( |
||||
[&fw = fw, &ti = ti, &d = d](auto v) -> bool |
||||
{ |
||||
constexpr auto cvt = decltype(v)::vt; |
||||
if constexpr(isDataSupported<T, cvt>) |
||||
return WriteData(fw, d.template Read<cvt>(ti)); |
||||
else |
||||
return false; |
||||
}, |
||||
vt); |
||||
}, |
||||
*this); |
||||
} |
||||
}; |
||||
|
||||
CLArgs ParseArgs(int argc, char** argv); |
||||
|
||||
#endif |
@ -0,0 +1,79 @@
|
||||
#include "basedata.h" |
||||
|
||||
#if !defined(M__SIMPLE2DDATA) |
||||
#define M__SIMPLE2DDATA |
||||
|
||||
class Simple2DData: public BaseData |
||||
{ |
||||
real x0 = 0.0, y0 = 0.0; |
||||
size_t nx = 0, ny = 0; |
||||
|
||||
public: |
||||
Simple2DData() = default; |
||||
|
||||
Simple2DData(size_t nx_, size_t ny_, real x0_, real y0_): BaseData(nx_ * ny_), x0(x0_), y0(y0_), nx(nx_), ny(ny_) {} |
||||
|
||||
const real& V(size_t i) const { return BaseData::V(i); } |
||||
real& V(size_t i) { return BaseData::V(i); } |
||||
|
||||
const real& operator()(size_t i) const { return BaseData::V(i); } |
||||
real& operator()(size_t i) { return BaseData::V(i); } |
||||
|
||||
const real& V(size_t ix, size_t iy) const { return V(iy * nx + ix); } |
||||
real& V(size_t ix, size_t iy) { return V(iy * nx + ix); } |
||||
|
||||
const real& operator()(size_t ix, size_t iy) const { return V(iy * nx + ix); } |
||||
real& operator()(size_t ix, size_t iy) { return V(iy * nx + ix); } |
||||
|
||||
size_t Nx() const { return nx; } |
||||
size_t Ny() const { return ny; } |
||||
|
||||
real Lon(size_t ix, size_t iy) const { return x0 + ix / 12.0; } |
||||
real Lat(size_t ix, size_t iy) const { return y0 + iy / 12.0; } |
||||
|
||||
real Lon(size_t i) const { return Lon(i % nx, i / nx); } |
||||
real Lat(size_t i) const { return Lat(i % nx, i / nx); } |
||||
|
||||
void InitCount(std::vector<size_t>& count) const |
||||
{ |
||||
count.resize(data.size()); |
||||
for(size_t i = 0; i < N(); i++) count[i] = (V(i) == fillval) ? 0 : 1; |
||||
} |
||||
|
||||
Simple2DData& Add(const Simple2DData& d, std::vector<size_t>& count) |
||||
{ |
||||
if(!d) return *this; |
||||
if(!*this) |
||||
{ |
||||
*this = d; |
||||
InitCount(count); |
||||
} |
||||
|
||||
if(N() != d.N() || N() != count.size()) return *this; |
||||
for(size_t i = 0; i < N(); i++) |
||||
if(d.V(i) != fillval) |
||||
{ |
||||
if(V(i) == fillval) |
||||
{ |
||||
V(i) = d(i); |
||||
count[i] = 1; |
||||
} |
||||
else |
||||
{ |
||||
V(i) += d(i); |
||||
count[i]++; |
||||
} |
||||
} |
||||
return *this; |
||||
} |
||||
|
||||
Simple2DData& Div(const std::vector<size_t>& count) |
||||
{ |
||||
if(N() != count.size()) return *this; |
||||
for(size_t i = 0; i < N(); i++) |
||||
if(count[i] != 0) V(i) /= count[i]; |
||||
return *this; |
||||
} |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,67 @@
|
||||
#include "mdatetime.h" |
||||
#include <memory> |
||||
#include <vector> |
||||
|
||||
#if !defined(M__TINDEXES) |
||||
#define M__TINDEXES |
||||
|
||||
using michlib::MDateTime; |
||||
|
||||
template<class T> std::vector<size_t> GetTIndexes(const T& adapter, const MDateTime& b, const MDateTime& e) |
||||
{ |
||||
std::vector<size_t> out; |
||||
auto nt = adapter.NTimes(); |
||||
const MDateTime& beg = (b < e) ? b : e; |
||||
const MDateTime& end = (b > e) ? b : e; |
||||
|
||||
if(beg > adapter.Time(nt - 1) || end < adapter.Time(0)) return out; |
||||
|
||||
size_t ib = 0, ie = nt - 1; |
||||
for(size_t i = 0; i < nt; i++) |
||||
if(adapter.Time(i) >= beg) |
||||
{ |
||||
ib = i; |
||||
break; |
||||
} |
||||
|
||||
for(size_t i = nt; i != 0; i--) |
||||
if(adapter.Time(i - 1) <= end) |
||||
{ |
||||
ie = i - 1; |
||||
break; |
||||
} |
||||
|
||||
out.resize(ie - ib + 1); |
||||
for(size_t i = 0; i < ie - ib + 1; i++) out[i] = i + ib; |
||||
return out; |
||||
} |
||||
|
||||
template<class T> std::vector<size_t> GetTIndexes(const T& adapter, const MString& regex) |
||||
{ |
||||
std::vector<size_t> out; |
||||
|
||||
std::unique_ptr<regex_t> regbuf(new regex_t); |
||||
if(0 != regcomp(regbuf.get(), regex.Buf(), REG_EXTENDED | REG_NOSUB)) return out; |
||||
|
||||
for(size_t i = 0; i < adapter.NTimes(); i++) |
||||
{ |
||||
MString date = adapter.Time(i).ToString(); |
||||
if(0 != regexec(regbuf.get(), date.Buf(), 0, 0, 0)) continue; |
||||
out.push_back(i); |
||||
} |
||||
|
||||
return out; |
||||
} |
||||
|
||||
template<class T> size_t GetTIndex(const T& adapter, const MDateTime& t) |
||||
{ |
||||
size_t nt = adapter.NTimes(); |
||||
|
||||
if(t <= adapter.Time(0)) return 0; |
||||
if(t >= adapter.Time(nt - 1)) return nt - 1; |
||||
for(size_t i = 0; i < nt - 1; i++) |
||||
if(t >= adapter.Time(i) && t <= adapter.Time(i + 1)) return (t - adapter.Time(i) <= adapter.Time(i + 1) - t) ? i : (i + 1); |
||||
return 0; |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,96 @@
|
||||
#include "MString.h" |
||||
#include <variant> |
||||
|
||||
#if !defined(M__VARTYPE) |
||||
#define M__VARTYPE |
||||
|
||||
using michlib::MString; |
||||
|
||||
namespace vartype |
||||
{ |
||||
enum class Vartype |
||||
{ |
||||
NONE, |
||||
U, |
||||
V, |
||||
TEMP, |
||||
SAL, |
||||
CHL |
||||
}; |
||||
|
||||
template<Vartype vt_> struct VartypeCarrier |
||||
{ |
||||
static const Vartype vt = vt_; |
||||
}; |
||||
|
||||
using VartypeUnion = std::variant<VartypeCarrier<Vartype::NONE>, VartypeCarrier<Vartype::U>, VartypeCarrier<Vartype::V>, VartypeCarrier<Vartype::TEMP>, |
||||
VartypeCarrier<Vartype::SAL>, VartypeCarrier<Vartype::CHL>>; |
||||
|
||||
template<class T, Vartype vt> |
||||
concept HasVar = requires(T t) |
||||
{ |
||||
{ |
||||
t.template Read<vt>(0)(0, 0) |
||||
} -> std::convertible_to<real>; |
||||
{ |
||||
t.template Read<vt>(std::vector<size_t>())(0, 0) |
||||
} -> std::convertible_to<real>; |
||||
}; |
||||
} // namespace vartype
|
||||
|
||||
template<class DT, vartype::Vartype vt> static constexpr bool isDataSupported = vartype::HasVar<DT, vt>; |
||||
|
||||
class VarType: public vartype::VartypeUnion |
||||
{ |
||||
auto VT() const |
||||
{ |
||||
return std::visit( |
||||
[](auto v) -> auto{ return decltype(v)::vt; }, *this); |
||||
} |
||||
|
||||
public: |
||||
template<vartype::Vartype vt> VarType(vartype::VartypeCarrier<vt>&& vc): vartype::VartypeUnion(std::move(vc)) {} |
||||
|
||||
VarType(MString str) |
||||
{ |
||||
str.ToLower(); |
||||
if(str == "u") *this = vartype::VartypeCarrier<vartype::Vartype::U>(); |
||||
if(str == "v") *this = vartype::VartypeCarrier<vartype::Vartype::V>(); |
||||
if(str == "t" || str == "temp" || str == "temperature") *this = vartype::VartypeCarrier<vartype::Vartype::TEMP>(); |
||||
if(str == "s" || str == "sal" || str == "salinity") *this = vartype::VartypeCarrier<vartype::Vartype::SAL>(); |
||||
if(str == "c" || str == "chl" || str == "chlorophyll") *this = vartype::VartypeCarrier<vartype::Vartype::CHL>(); |
||||
} |
||||
|
||||
MString Name() const |
||||
{ |
||||
switch(VT()) |
||||
{ |
||||
case(vartype::Vartype::NONE): return "none"; |
||||
case(vartype::Vartype::U): return "U"; |
||||
case(vartype::Vartype::V): return "V"; |
||||
case(vartype::Vartype::TEMP): return "Temperature"; |
||||
case(vartype::Vartype::SAL): return "Salinity"; |
||||
case(vartype::Vartype::CHL): return "Chlorophyll"; |
||||
} |
||||
return "none"; |
||||
} |
||||
|
||||
bool Ok() const { return VT() != vartype::Vartype::NONE; } |
||||
explicit operator bool() const { return Ok(); } |
||||
bool operator==(const VarType& vt) const { return VT() == vt.VT(); } |
||||
bool operator!=(const VarType& vt) const { return VT() != vt.VT(); } |
||||
template<class Data> bool isSupported() const |
||||
{ |
||||
return std::visit( |
||||
[](const auto v) -> bool |
||||
{ |
||||
if constexpr(isDataSupported<Data, decltype(v)::vt>) |
||||
return true; |
||||
else |
||||
return false; |
||||
}, |
||||
*this); |
||||
} |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,10 @@
|
||||
set(EXENAME odm) |
||||
|
||||
find_library(netcdf netcdf REQUIRED) |
||||
|
||||
include_directories(../michlib/michlib) |
||||
|
||||
file(GLOB srcs *.cpp) |
||||
add_executable(${EXENAME} ${srcs}) |
||||
target_link_libraries(${EXENAME} ${linker_options} ${netcdf}) |
||||
set_target_properties(${EXENAME} PROPERTIES POSITION_INDEPENDENT_CODE ON) |
@ -0,0 +1,29 @@
|
||||
#define MICHLIB_NOSOURCE |
||||
#include "GPL.h" |
||||
#include "odm.h" |
||||
|
||||
CLArgs ParseArgs(int argc, char** argv) |
||||
{ |
||||
CLArgs out; |
||||
|
||||
out["_name"] = argv[0]; |
||||
for(int i = 0; i < argc; i++) |
||||
{ |
||||
MString carg = argv[i]; |
||||
out["_arg" + MString(i)] = carg; |
||||
|
||||
for(size_t c = 0; c < carg.Len(); c++) |
||||
if(carg[c] == '=') |
||||
{ |
||||
MString name = carg.SubStr(1, c); |
||||
MString val = carg.SubStr(c + 2, carg.Len() - c - 1); |
||||
out[name] = val; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
SList sl; |
||||
michlib_internal::ParseParameterFile("/etc/michlibconf", sl, 0); |
||||
|
||||
return out; |
||||
} |
@ -0,0 +1,168 @@
|
||||
#include "odm.h" |
||||
#include "GPL.h" |
||||
|
||||
inline void Usage(const MString& arg0) |
||||
{ |
||||
message(arg0 + " (<key>=<value>...)"); |
||||
message("Keys are:"); |
||||
message(" source. Required. May be: NEMO"); |
||||
message(" var. Required. May be: temp, sal or chl"); |
||||
message(" time. Time moment or regular expression. If present, timeb and timee must be absent"); |
||||
message(" timeb, timee. Time interval. If present, time must be absent"); |
||||
message(" out. Output file. Default: out.bin"); |
||||
message(" Keys for source=NEMO"); |
||||
message(" var can be only temp or sal"); |
||||
message(" dataset. Can be DT, NRT or NRT6. Default: DT"); |
||||
message(" cred. Login and password for COPERNICUS site. Default works"); |
||||
message(" proxy. Proxy for access to COPERNICUS. Default works"); |
||||
message(" layer and/or depth. Layer or depth of NEMO dataset. If depth is specified, layer is ignored. Default: layer=0"); |
||||
message(" lonb, lone, latb, late. Required. Region of interest"); |
||||
} |
||||
|
||||
int main(int argc, char** argv) |
||||
{ |
||||
if(argc == 1) |
||||
{ |
||||
Usage(argv[0]); |
||||
return 2; |
||||
} |
||||
auto args = ParseArgs(argc, argv); |
||||
|
||||
if(!args.contains("source")) |
||||
{ |
||||
errmessage("No source specified!"); |
||||
return 1; |
||||
} |
||||
|
||||
VarType vtype(args["var"]); |
||||
if(!vtype) |
||||
{ |
||||
errmessage("Incorrect or no variable specified"); |
||||
return 1; |
||||
} |
||||
|
||||
michlib_internal::ParameterListEx pars; |
||||
pars.UsePrefix(""); |
||||
|
||||
pars.SetParameter("source", args["source"]); |
||||
pars.SetParameter("variable", vtype.Name()); |
||||
|
||||
Data data; |
||||
|
||||
if(args["source"] == "NEMO") |
||||
{ |
||||
if(!vtype.isSupported<NEMOData>()) |
||||
{ |
||||
errmessage("Variable " + args["var"] + " is unsupported by NEMO"); |
||||
return 1; |
||||
} |
||||
|
||||
GPL.UsePrefix("AVISO"); |
||||
NEMOData ndata; |
||||
MString dataset = args["dataset"]; |
||||
if(!dataset.Exist()) dataset = "DT"; |
||||
MString cred = args["cred"]; |
||||
if(!cred.Exist()) cred = GPL.ParameterSValue("COPERNICUS_USER", ""); |
||||
MString proxy; |
||||
if(args.contains("proxy")) |
||||
MString proxy = args["proxy"]; |
||||
else |
||||
proxy = GPL.ParameterSValue("COPERNICUS_PROXY", ""); |
||||
|
||||
if(!ndata.Open(dataset, cred, proxy)) |
||||
{ |
||||
errmessage("Can't open NEMO dataset"); |
||||
return 1; |
||||
} |
||||
|
||||
size_t layer = 0; |
||||
if(args.contains("layer")) layer = args["layer"].ToInteger<size_t>(); |
||||
if(!args.contains("depth") && layer >= ndata.NDepths()) |
||||
{ |
||||
errmessage(MString("Layer ") + layer + " is too deep!"); |
||||
return 1; |
||||
} |
||||
real depth = args.contains("depth") ? args["depth"].ToReal() : ndata.Depth(layer); |
||||
|
||||
if(!(args.contains("lonb") && args.contains("lone") && args.contains("latb") && args.contains("late"))) |
||||
{ |
||||
errmessage("Region not specified (lonb, lone, latb, late)"); |
||||
return 1; |
||||
} |
||||
if(!ndata.SetRegion(args["lonb"].ToReal(), args["lone"].ToReal(), args["latb"].ToReal(), args["late"].ToReal(), depth)) |
||||
{ |
||||
errmessage("Can't set region"); |
||||
return 1; |
||||
} |
||||
|
||||
pars.SetParameter("depth", depth); |
||||
pars.SetParameter("layer", ndata.Layer()); |
||||
pars.SetParameter("dataset", dataset); |
||||
pars.SetParameter("lonb", args["lonb"].ToReal()); |
||||
pars.SetParameter("latb", args["latb"].ToReal()); |
||||
pars.SetParameter("lone", args["lone"].ToReal()); |
||||
pars.SetParameter("late", args["late"].ToReal()); |
||||
|
||||
data = DataVariants(std::move(ndata)); |
||||
} |
||||
else |
||||
{ |
||||
errmessage("Unknown source " + args["source"]); |
||||
return 1; |
||||
} |
||||
|
||||
if(args.contains("time") && (args.contains("timeb") || args.contains("timee"))) |
||||
{ |
||||
errmessage("Time must be set via time parameter or timeb and timee parameter but not via both"); |
||||
return 1; |
||||
} |
||||
|
||||
if(!(args.contains("time") || (args.contains("timeb") && args.contains("timee")))) |
||||
{ |
||||
errmessage("Time must be set via time parameter or timeb and timee parameter"); |
||||
return 1; |
||||
} |
||||
|
||||
BFileW fw; |
||||
MString name = args["out"]; |
||||
if(!name.Exist()) name = "out.bin"; |
||||
|
||||
fw.Create(name, 3); |
||||
/*
|
||||
if(!fw.Create(name,3)) |
||||
{ |
||||
errmessage("Can't create file "+name); |
||||
return 1; |
||||
} |
||||
*/ |
||||
fw.SetParameters(pars); |
||||
fw.UsePrefix(""); |
||||
|
||||
if(args.contains("time")) |
||||
{ |
||||
MDateTime time; |
||||
if(time.FromString(args["time"])) // One date
|
||||
{ |
||||
auto it = GetTIndex(data, time); |
||||
fw.SetParameter("time", data.Time(it).ToString()); |
||||
data.Write(fw, vtype, std::vector<size_t>(1, it)); |
||||
} |
||||
else // Regular expression
|
||||
{ |
||||
fw.SetParameter("timeregex", args["time"]); |
||||
data.Write(fw, vtype, GetTIndexes(data, args["time"])); |
||||
} |
||||
} |
||||
else // Bdate, edate
|
||||
{ |
||||
MDateTime tb(args["timeb"]), te(args["timee"]); |
||||
fw.SetParameter("timeb", tb.ToString()); |
||||
fw.SetParameter("timee", te.ToString()); |
||||
data.Write(fw, vtype, GetTIndexes(data, tb, te)); |
||||
} |
||||
|
||||
fw.Finalize(); |
||||
fw.Close(); |
||||
|
||||
return 0; |
||||
} |
Loading…
Reference in new issue