-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathintensity_clippers.cpp
138 lines (105 loc) · 4.26 KB
/
intensity_clippers.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <rf_kernels/mean_rms.hpp>
#include <rf_kernels/intensity_clipper.hpp>
#include "rf_pipelines_internals.hpp"
using namespace std;
namespace rf_pipelines {
#if 0
}; // pacify emacs c-mode
#endif
struct intensity_clipper_transform : public wi_transform
{
// (Frequency, time) downsampling factors and axis.
const int Df;
const int Dt;
const rf_kernels::axis_type axis;
// Clipping thresholds.
const int niter;
const double sigma;
const double iter_sigma;
const bool two_pass;
// Created in set_stream()
unique_ptr<rf_kernels::intensity_clipper> kernel;
intensity_clipper_transform(int Df_, int Dt_, rf_kernels::axis_type axis_, int nt_chunk_, double sigma_, int niter_, double iter_sigma_, bool two_pass_)
: wi_transform("intensity_clipper"),
Df(Df_),
Dt(Dt_),
axis(axis_),
niter(niter_),
sigma(sigma_),
iter_sigma(iter_sigma_ ? iter_sigma_ : sigma_),
two_pass(two_pass_)
{
stringstream ss;
ss << "intensity_clipper(nt_chunk=" << nt_chunk_ << ", axis=" << axis
<< ", sigma=" << sigma << ", niter=" << niter << ", iter_sigma=" << iter_sigma
<< ", Df=" << Df << ", Dt=" << Dt << ", two_pass=" << two_pass << ")";
this->name = ss.str();
this->nt_chunk = nt_chunk_;
this->kernel_chunk_size = 8 * Dt;
this->nds = 0; // allows intensity_clipper to run in a wi_sub_pipeline.
if ((nt_chunk == 0) && (axis != rf_kernels::AXIS_FREQ))
throw runtime_error("rf_pipelines::intensity_clipper: nt_chunk must be specified (unless axis=AXIS_FREQ)");
// Can't construct the kernel yet, since 'nfreq' and 'nds' are not known until bind().
// However, for argument checking purposes, we construct a dummy kernel with (nfreq,nt_chunk)=(Df,8*Dt).
// FIXME eventually there will be a constructor argument 'allocate=false' that will make sense here.
rf_kernels::intensity_clipper dummy(Df, 8*Dt, axis, sigma, Df, Dt, niter, iter_sigma, two_pass);
}
virtual ~intensity_clipper_transform() { }
// Called after (nfreq, nds) are initialized.
virtual void _bind_transform(Json::Value &json_attrs) override
{
if (nfreq % Df)
throw runtime_error("rf_pipelines::intensity_clipper: nfreq (=" + to_string(nfreq)
+ ") is not divisible by frequency downsampling factor Df=" + to_string(Df));
// Note xdiv(nt_chunk, nds) here.
this->kernel = make_unique<rf_kernels::intensity_clipper> (nfreq, xdiv(nt_chunk,nds), axis, sigma, Df, Dt, niter, iter_sigma, two_pass);
}
virtual void _process_chunk(float *intensity, ssize_t istride, float *weights, ssize_t wstride, ssize_t pos) override
{
this->kernel->clip(intensity, istride, weights, wstride);
}
virtual Json::Value jsonize() const override
{
Json::Value ret;
ret["class_name"] = "intensity_clipper";
ret["Df"] = Df;
ret["Dt"] = Dt;
ret["axis"] = rf_kernels::axis_type_to_string(axis);
ret["nt_chunk"] = int(this->get_prebind_nt_chunk());
ret["sigma"] = sigma;
ret["niter"] = niter;
ret["iter_sigma"] = iter_sigma;
ret["two_pass"] = two_pass;
return ret;
}
virtual void _unbind_transform() override
{
this->kernel.reset();
}
static shared_ptr<intensity_clipper_transform> from_json(const Json::Value &j)
{
int Df = int_from_json(j, "Df");
int Dt = int_from_json(j, "Dt");
int niter = int_from_json(j, "niter");
int nt_chunk = int_from_json(j, "nt_chunk");
bool two_pass = bool_from_json(j, "two_pass");
double sigma = double_from_json(j, "sigma");
double iter_sigma = double_from_json(j, "iter_sigma");
rf_kernels::axis_type axis = axis_type_from_json(j, "axis");
return make_shared<intensity_clipper_transform> (Df, Dt, axis, nt_chunk, sigma, niter, iter_sigma, two_pass);
}
};
namespace {
struct _init {
_init() {
pipeline_object::register_json_deserializer("intensity_clipper", intensity_clipper_transform::from_json);
}
} init;
}
// -------------------------------------------------------------------------------------------------
// Externally visible
shared_ptr<wi_transform> make_intensity_clipper(int nt_chunk, rf_kernels::axis_type axis, double sigma, int niter, double iter_sigma, int Df, int Dt, bool two_pass)
{
return make_shared<intensity_clipper_transform> (Df, Dt, axis, nt_chunk, sigma, niter, iter_sigma, two_pass);
}
} // namespace rf_pipelines