Newer
Older
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
//
// splinterpolator.h
//
// Jesper Andersson, FMRIB Image Analysis Group
//
// Copyright (C) 2008 University of Oxford
//
// CCOPYRIGHT
//
#ifndef splinterpolator_h
#define splinterpolator_h
#include <vector>
#include <string>
#include <cmath>
#include "newmat.h"
#include "miscmaths/miscmaths.h"
namespace SPLINTERPOLATOR {
enum ExtrapolationType {Zeros, Constant, Mirror, Periodic};
class SplinterpolatorException: public std::exception
{
private:
std::string m_msg;
public:
SplinterpolatorException(const std::string& msg) throw(): m_msg(msg) {}
virtual const char *what() const throw() {
return string("FslSplines::" + m_msg).c_str();
}
~SplinterpolatorException() throw() {}
};
template<class T>
class Splinterpolator
{
public:
// Constructors
Splinterpolator() : _valid(false) {}
Splinterpolator(const T *data, const std::vector<unsigned int>& dim, unsigned int order=3, std::vector<ExtrapolationType> et(3,Zeros))
{
common_construction(data,dim,order,et);
}
Splinterpolator(const T *data, const std::vector<unsigned int>& dim, unsigned int order, ExtrapolationType et)
{
std::vector<ExtrapolationType> ett(dim.size(),et);
common_construction(data,dim,order,ett);
}
// Destructor
~Splinterpolator() { if(_valid) delete [] _coef; }
//
// Here we declare nested helper-class SplineColumn
//
class SplineColumn
{
public:
// Constructor
SplineColumn(unsigned int sz, unsigned int step) : _sz(sz), _step(step) { _col = new double[_sz]; }
// Destructor
~SplineColumn() { delete [] _col; }
// Extract a column from a volume
Get(const T *dp)
{
for (unsigned int i=0; i<_sz; i++, dp+=_step) _col[i] = static_cast<double>(*dp);
}
// Insert column into volume
Set(T *dp)
{
T test = 1.5;
if (test == 1) { // If T is not float or double
for (unsigned int i=0; i<_sz; i++, dp+=_step) *dp = static_cast<T>(_col[i] + 0.5); // Round to nearest integer
}
else {
for (unsigned int i=0; i<_sz; i++, dp+=_step) *dp = static_cast<T>(_col[i]);
}
}
// Deconvolve column
Deconv(unsigned int order, ExtrapolationType et) {};
private:
unsigned int _sz;
unsigned int _step;
double *_col;
SplineColumn(const SplineColumn& sc); // Don't allow copy-construction
SplineColumn& operator=(const SplineColumn& sc); // Dont allow assignment
};
void Set(const T *data, const std::vector<unsigned int>& dim, unsigned int order=3, std::vector<ExtrapolationType> et(3,Zeros))
{
if (_valid) delete [] _coef;
common_construction(data,dim,order,et);
}
private:
bool _valid; // Decides if neccessary information has been set or not
T *_coef; // Volume of spline coefficients
unsigned int _order; // Order of splines
std::vector<unsigned int> _dim; // Dimensions of data
std::vector<ExtrapolationType> _et; // How to do extrapolation
//
// Private helper-functions
//
void common_construction(const T *data, const std::vector<unsigned int>& dim, unsigned int order, const std::vector<ExtrapolationType>& et);
void calc_coef(const T *data);
void deconv_along(unsigned int dim);
//
// Disallowed member functions
//
Splinterpolator(const Splinterpolator& s); // Don't allow copy-construction
Splinterpolator& operator=(const Splinterpolator& s); // Don't allow assignment
};
template<class T>
void Splinterpolator<T>::common_construction(const T *data, const std::vector<unsigned int>& dim, unsigned int order, const std::vector<ExtrapolationType>& et)
{
if (!dim.size()) throw SplinterpolatorException("Splinterpolator::common_construction: data has zeros dimensions");
if (!dim.size() > 5) throw SplinterpolatorException("Splinterpolator::common_construction: data cannot have more than 5 dimensions");
if (dim.size() != et.size()) throw SplinterpolatorException("Splinterpolator::common_construction: dim and et must have the same size");
for (unsigned int i=0; i<dim.size(); i++) if (!dim[i]) throw SplinterpolatorException("Splinterpolator::common_construction: data cannot have zeros size in any direction");
if (order > 7) throw SplinterpolatorException("Splinterpolator::common_construction: spline order must be lesst than 7");
if (!data) throw SplinterpolatorException("Splinterpolator::common_construction: zero data pointer");
for (unsigned int ts=1, i=0; i<dim.size(); i++) ts *= dim[i];
_coef = new T[ts];
_order = order;
_dim.resize(5); = dim;
_et = et;
calc_coef(data);
_valid = true;
}
template<class T>
void Splinterpolator<T>::calc_coef(const T *data)
{
// Put the original data into _coef
//
for (unsigned int ts=1, i=0; i<dim.size(); i++) ts *= dim[i];
memcpy(_coef,data,ts*sizeof(T));
if (_order < 2) return; // If nearest neighbour or linear, that's all we need
// Loop over all non-singleton dimensions and deconvolve along them
//
std::vector<unsigned int> tdim(dim.size()-1,0);
for (unsigned int cdir=0; cdir<dim.size(); cdir++) {
if (dim[cdir] > 1) deconv_along(cdir)
}
return;
}
template<class T>
void Splinterpolator<T>::deconv_along(unsigned int dim);
{
T *dp = _coef;
// Set up to reflect "missing" dimension
//
std::vector<unsigned int> rdim(4,1); // Sizes along remaining dimensions
std::vector<unsigned int> rstep(4,1); // Step-sizes (in "volume") of remaining dimensions
unsigned int mdim = 1; // Size along "missing" dimension
unsigned int mstep = 1; // Step-size along "missing" dimension
for (unsigned int i=0, j=0, s=1; i<5; i++) {
if (i == dim) { // If it is our "missing" dimension
mdim = _dim(i);
mstep = ss;
}
else {
rdim[j] = _dim[i];
rstep[j++] = ss;
}
ss *= _dim[i];
}
SplineColumn<T> col(mdim,mstep); // Column helps us do the job
for (unsigned int l=0; l<rdim[3]; l++, dp+=rstep[3]) {
for (unsigned int k=0; k<rdim[2]; k++, dp+=rstep[2]) {
for (unsigned int j=0; j<rdim[1]; j++, dp+=rstep[1]) {
for (unsigned int i=0; i<rdim[0]; i++, dp+=rstep[0]) {
col.Get(dp); // Extract a column from the volume
col.Deconv(_order,_et[dim]); // Deconvolve it
col.Set(dp); // Put back the deconvolved column
}
}
}
}
return;
}
} // End namespace SPLINTERPOLATOR
#endif // End #ifndef splinterpolator.h