Skip to content

Instantly share code, notes, and snippets.

@ubnt-intrepid
Last active August 29, 2015 14:27
Show Gist options
  • Save ubnt-intrepid/fc158d1b1a6045ad7b1b to your computer and use it in GitHub Desktop.
Save ubnt-intrepid/fc158d1b1a6045ad7b1b to your computer and use it in GitHub Desktop.
#include <iostream>
#include <string>
#include <vector>
#include "time_series.hpp"
template <typename T = double, typename Duration = std::chrono::seconds>
my::time_series<T, Duration> load_series(std::string const& file_path)
{
// load datasets.
std::vector<T> data;
std::ostream ifs(file_path, std::ios::in);
for (std::string line; ifs && std::getline(ifs, line);)
{
data.push_back(boost::lexical_cast<T>(line));
}
return my::time_series<T, Duration>(std::move(data));
}
int main(int argc, char const* argv[])
{
using namespace std;
using namespace std::chrono;
auto series1 = load_series<double, seconds>("hogehoge_sec.csv");
// => time_series<double, seconds>
// upsampling
auto series2 = series1.resample<milliseconds>();
auto series2 = series1.resample<milliseconds>(my::upsampling_mode::FILTERED);
auto series2 = series1.resample<milliseconds>(my::upsampling_mode::HOLDED);
// => time_series<double, chrono::milliseconds>
// downsampling
auto series3 = series1.resample<minutes>();
auto series3 = series1.resample<minutes>(my::downsampling_mode::FILTERED);
auto series3 = series1.resample<minutes>(my::downsampling_mode::AVERAGE);
// => time_series<double, chrono::minutes>
// remove duration informations.
vector<double> values3 = series3.values();
vector<double> hogehoge_min
= load_series("hogehoge_sec.csv")
.resample<minutes>(my::downsampling_mode::AVERAGE)
.values();
}
#include <chrono>
#include <vector>
#include <ratio>
#include <type_traits>
namespace my {
enum class downsampling_mode {
DEFAULT, // 間引きのみ(フィルタをかけない)
FILTERED, // 変換前にデシメーションフィルタに通す
AVERAGE, // 直前のサンプリングまでのデータの移動平均を取る
};
enum class upsampling_mode {
DEFAULT, // 周期の変更のみ(補完なし)
FILTERED, // 変換後にインターポレーションフィルタに通す
HOLDED, // 0次ホールド
};
namespace detail {
template <class D1, class D2>
struct is_downsampling {
using ratio_t = std::ratio_divide<typename D1::period, typename D2::period>;
static constexpr value = ratio_t::num < ratio_t::den;
};
template <typename T, typename Ratio>
std::vector<T> upsample_default(std::vector<T> const& src)
{
constexpr uintmax_t span = Ratio::num; // 整数倍のみ
std::vector<T> dest;
dest.reserve(src.size() * span);
for (auto const& item : src) {
dest.push_back(item);
dest.resize(dest.size() + span - 1, T(0));
}
return dest;
}
template <typename T, typename Ratio>
std::vector<T> upsample_filtered(std::vector<T> const& src)
{
/* ... */
}
template <typename T>
std::vector<T> upsample_holded(std::vector<T> const& src)
{
constexpr uintmax_t span = Ratio::num; // 整数倍のみ
std::vector<T> dest;
dest.reserve(src.size() * span);
for (auto const& item : src) {
dest.resize(dest.size() + span, item);
}
return dest;
}
template <class D1, class D2>
struct upsampling
{
using ratio_t = std::ratio_divide<typename D1::period, typename D2::period>;
template <typename T>
static std::vector<T> apply(std::vector<T> const& src, upsampling_mode mode)
{
switch (mode) {
case upsampling_mode::DEFAULT: return upsample_default<ratio_t>(src);
case upsampling_mode::FILTERED: return upsample_filtered<ratio_t>(src);
case upsampling_mode::HOLDED: return upsample_holded<ratio_t>(src);
}
}
};
template <class D>
struct upsampling<D, D>
{
template <typename T>
inline static std::vector<T> apply(std::vector<T> const& src, upsampling_mode) {
return src; // do nothing.
}
};
template <class D1, class D2>
struct downsampling
{
using ratio_t = std::ratio_divide<typename D1::period, typename D2::period>;
template <typename T>
static std::vector<T> apply(std::vector<T> const& src, downsampling_mode mode)
{
switch (mode) {
case upsampling_mode::DEFAULT: {
// hogehoge.
return ...;
}
case upsampling_mode::FILTERED: {
// hogehoge.
return ...
}
case upsampling_mode::AVERAGE: {
// hogehoge.
return ...
}
}
}
};
} // namespace detail;
template <class D1, class D2>
using is_downsampling = std::integral_constant<bool, detail::is_downsampling<D1, D2>::value>;
template <typename T, class D1, class D2>
std::vector<T> upsample(std::vector<T> const& src, upsampling_mode mode) {
return detail::upsampling<D1, D2>::apply(src, mode);
}
template <typename T, class D1, class D2>
std::vector<T> downsample(std::vector<T> const& src, downsampling_mode mode) {
return detail::downsampling<D1, D2>::apply(src, mode);
}
template <typename T,
typename Duration = std::chrono::seconds>
class time_series
{
std::vector<T> body_;
public:
using value_type = T;
using duration_type = Duration;
public:
time_series() = delete;
time_series(time_series const&) = default;
time_series(time_series &&) = default;
time_series& operator=(time_series const&) = default;
time_series& operator=(time_series &&) = default;
time_series(std::vector<T> const& src)
: body_(src)
{
}
time_series(std::vector<T> && src)
: body_(std::move(src))
{
}
template <typename SrcDuration>
time_series(time_series<T, SrcDuration> const& other, downsampling_mode mode)
: body_(other.resample<Duration>(mode).values())
{
}
template <typename SrcDuration>
time_series(time_series<T, SrcDuration> const& other, upsampling_mode mode)
: body_(other.resample<Duration>(mode).values())
{
}
public:
inline std::vector<T> const& values() const noexcept { return body_; }
inline std::size_t size() const noexcept { return body_.size(); }
public:
template <typename ToDuration>
time_series<T, ToDuration> resample(downsampling_mode mode) const
{
static_assert(is_downsampling<Duration, ToDuration>::value, "cannot upsample");
std::vector<T> downsampled = downsample<Duration, ToDuration>(body_, mode);
return time_series<T, ToDuration>(std::move(downsampled));
}
template <typename ToDuration>
time_series<T, ToDuration> resample(upsampling_mode mode) const
{
static_assert(!is_downsampling<Duration, ToDuration>::value, "cannot downsample");
std::vector<T> upsampled = upsample<Duration, ToDuration>(body_, mode);
return time_series<T, ToDuration>(std::move(upsampled));
}
};
} // namespace my;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment