00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef GRIDDING_H
00019 #define GRIDDING_H
00020
00021 #include <odindata/data.h>
00022 #include <odindata/utils.h>
00023
00024 #include <odinpara/jdxfilter.h>
00025
00036 template<int N_rank>
00037 struct GriddingPoint {
00038 GriddingPoint(const TinyVector<float,N_rank>& c=0.0, float w=1.0) : coord(c), weight(w) {}
00039
00040 TinyVector<float,N_rank> coord;
00041 float weight;
00042 };
00043
00044
00046
00051 template<typename T, int N_rank>
00052 class Gridding {
00053
00054 public:
00055
00059 Gridding() : shape(0) {}
00060
00070 Array<float,N_rank> init(const TinyVector<int,N_rank>& dst_shape, const TinyVector<float,N_rank>& dst_extent,
00071 const STD_vector<GriddingPoint<N_rank> >& src_coords,
00072 const JDXfilter& kernel, float kernel_diameter);
00073
00080 template<int N_rank_in>
00081 Array<T,N_rank> operator () (const Array<T,N_rank_in>& src, unsigned int offset=0) const;
00082
00083
00084 private:
00085 TinyVector<int,N_rank> shape;
00086
00087
00088 STD_vector< STD_vector< STD_pair<TinyVector<int,N_rank>, float> > > recipe;
00089
00090
00091 };
00092
00094
00095 template <typename T, int N_rank>
00096 Array<float,N_rank> Gridding<T,N_rank>::init(const TinyVector<int,N_rank>& dst_shape, const TinyVector<float,N_rank>& dst_extent,
00097 const STD_vector<GriddingPoint<N_rank> >& src_coords,
00098 const JDXfilter& kernel, float kernel_diameter) {
00099 Log<OdinData> odinlog("Gridding","init");
00100
00101 shape=dst_shape;
00102
00103 unsigned int nsrc=src_coords.size();
00104
00105 ODINLOG(odinlog,normalDebug) << "nsrc/kernel/kernel_diameter=" << nsrc << "/" << kernel.get_function_name() << "/" << kernel_diameter << STD_endl;
00106
00107 recipe.resize(nsrc);
00108
00109
00110 Array<float,N_rank> weight_sum(dst_shape);
00111 weight_sum=0.0;
00112
00113 TinyVector<float,N_rank> dst_step=dst_extent/dst_shape;
00114 ODINLOG(odinlog,normalDebug) << "dst_step=" << dst_step << STD_endl;
00115
00116 TinyVector<float,N_rank> kernel_extent=kernel_diameter/dst_step;
00117 ODINLOG(odinlog,normalDebug) << "kernel_extent=" << kernel_extent << STD_endl;
00118
00119 TinyVector<float,N_rank> offset=0.5*(dst_shape-1.0);
00120
00121
00122 for(unsigned int isrc=0; isrc<nsrc; isrc++) {
00123 const GriddingPoint<N_rank>& point=src_coords[isrc];
00124
00125
00126 TinyVector<float,N_rank> root=point.coord/dst_step + offset;
00127 ODINLOG(odinlog,normalDebug) << "root=" << root << STD_endl;
00128
00129 TinyVector<int,N_rank> lowindex=(root-0.5*kernel_extent)+0.5;
00130 TinyVector<int,N_rank> uppindex=(root+0.5*kernel_extent);
00131 ODINLOG(odinlog,normalDebug) << "lowindex/uppindex=" << lowindex << "/" << uppindex << STD_endl;
00132
00133
00134 TinyVector<int,N_rank> neighbours=uppindex-lowindex+1;
00135 ODINLOG(odinlog,normalDebug) << "neighbours=" << neighbours << STD_endl;
00136
00137
00138 STD_vector<STD_pair<TinyVector<int,N_rank>, float> >& dstvec=recipe[isrc];
00139 dstvec.clear();
00140 for(int ineighb=0; ineighb<product(neighbours); ineighb++) {
00141 TinyVector<int,N_rank> neighb_index=index2extent(neighbours, ineighb);
00142
00143
00144 TinyVector<int,N_rank> index=lowindex+neighb_index;
00145 bool ongrid=true;
00146 for(int i=0; i<N_rank; i++) {
00147 if(index(i)<0) ongrid=false;
00148 if(index(i)>=dst_shape(i)) ongrid=false;
00149 }
00150
00151
00152 if(ongrid) {
00153 TinyVector<float,N_rank> diff=(root-index)*dst_step;
00154 float radius=sqrt(sum(diff*diff))/(0.5*kernel_diameter);
00155 float weight=point.weight*kernel.calculate(radius);
00156 if(weight>=0.0) dstvec.push_back(STD_pair<TinyVector<int,N_rank>, float>(index,weight));
00157 }
00158 }
00159
00160
00161 for(unsigned int idst=0; idst<dstvec.size(); idst++) {
00162 weight_sum(dstvec[idst].first)+=dstvec[idst].second;
00163 }
00164
00165 }
00166
00167
00168
00169 for(unsigned int isrc=0; isrc<nsrc; isrc++) {
00170 STD_vector< STD_pair<TinyVector<int,N_rank>, float> >& dstvec=recipe[isrc];
00171 for(unsigned int idst=0; idst<dstvec.size(); idst++) {
00172 STD_pair<TinyVector<int,N_rank>, float>& weightpair=dstvec[idst];
00173 float weightsum=weight_sum(weightpair.first);
00174 if(weightsum>0.0) weightpair.second/=weightsum;
00175 }
00176 }
00177
00178 return weight_sum;
00179 }
00180
00182
00183 template <typename T, int N_rank>
00184 template<int N_rank_in>
00185 Array<T,N_rank> Gridding<T,N_rank>::operator () (const Array<T,N_rank_in>& src, unsigned int offset) const {
00186 Log<OdinData> odinlog("Gridding","()");
00187 Array<T,N_rank> result;
00188
00189 unsigned int nsrc=src.size();
00190 if((offset+nsrc)>recipe.size()) {
00191 ODINLOG(odinlog,errorLog) << "Max index of src=" << offset+nsrc << " exceeds recipe.size()=" << recipe.size() << STD_endl;
00192 return result;
00193 }
00194
00195 result.resize(shape);
00196 result=T(0);
00197
00198 for(unsigned int isrc=0; isrc<nsrc; isrc++) {
00199 const STD_vector< STD_pair<TinyVector<int,N_rank>, float> >& dstvec=recipe[offset+isrc];
00200 for(unsigned int idst=0; idst<dstvec.size(); idst++) {
00201 const STD_pair<TinyVector<int,N_rank>, float>& weightpair=dstvec[idst];
00202 result(weightpair.first) += weightpair.second * src(index2extent(src.shape(),isrc));
00203 }
00204 }
00205
00206
00207 return result;
00208 }
00209
00210
00211
00213
00217 template<typename T, int N_rank, bool OnPixelRot=false>
00218 class CoordTransformation {
00219
00220 public:
00221
00227 CoordTransformation(const TinyVector<int,N_rank>& shape, const TinyMatrix<float,N_rank,N_rank>& rotation, const TinyVector<float,N_rank>& offset, float kernel_size=2.5);
00228
00232 Array<T,N_rank> operator () (const Array<T,N_rank>& A) const;
00233
00234 private:
00235 TinyVector<int,N_rank> shape_cache;
00236 Gridding<T,N_rank> gridder;
00237 };
00238
00240
00241 template <typename T, int N_rank, bool OnPixelRot>
00242 CoordTransformation<T,N_rank,OnPixelRot>::CoordTransformation(const TinyVector<int,N_rank>& shape, const TinyMatrix<float,N_rank,N_rank>& rotation, const TinyVector<float,N_rank>& offset, float kernel_size)
00243 : shape_cache(shape) {
00244 Log<OdinData> odinlog("CoordTransformation","CoordTransformation");
00245
00246 int nsrc=product(shape);
00247 STD_vector<GriddingPoint<N_rank> > src_coords(nsrc);
00248 ODINLOG(odinlog,normalDebug) << "N_rank/nsrc=" << N_rank << "/" << nsrc << STD_endl;
00249
00250 TinyVector<float,N_rank> extent_half;
00251 if(OnPixelRot) extent_half=shape/2;
00252 else extent_half=0.5*(shape-1);
00253 TinyVector<int,N_rank> index;
00254 TinyVector<float,N_rank> findex;
00255 for(int isrc=0; isrc<nsrc; isrc++) {
00256 index=index2extent(shape, isrc);
00257
00258
00259 findex=index-extent_half;
00260 src_coords[isrc].coord=product(rotation,findex)+offset;
00261 }
00262 ODINLOG(odinlog,normalDebug) << "source done" << STD_endl;
00263
00264
00265 JDXfilter gridkernel;
00266 gridkernel.set_function("Gauss");
00267 gridder.init(shape, shape, src_coords, gridkernel, kernel_size);
00268 }
00269
00271
00272
00273 template <typename T, int N_rank, bool OnPixelRot>
00274 Array<T,N_rank> CoordTransformation<T,N_rank,OnPixelRot>::operator () (const Array<T,N_rank>& A) const {
00275 Log<OdinData> odinlog("CoordTransformation","()");
00276 if(A.shape()!=shape_cache) {
00277 ODINLOG(odinlog,errorLog) << "Shape mismatch" << STD_endl;
00278 return A;
00279 }
00280
00281 return gridder(A);
00282 }
00283
00284
00290 #endif