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;
00117 for(int irank=0; irank<N_rank; irank++) {
00118 if(dst_step(irank)>0.0) kernel_extent(irank)=kernel_diameter/dst_step(irank);
00119 else kernel_extent(irank)=0.0;
00120 }
00121 ODINLOG(odinlog,normalDebug) << "kernel_extent=" << kernel_extent << STD_endl;
00122
00123 TinyVector<float,N_rank> offset=0.5*(dst_shape-1.0);
00124
00125
00126 for(unsigned int isrc=0; isrc<nsrc; isrc++) {
00127 const GriddingPoint<N_rank>& point=src_coords[isrc];
00128
00129
00130 TinyVector<float,N_rank> root;
00131 for(int irank=0; irank<N_rank; irank++) {
00132 if(dst_step(irank)>0.0) root(irank)=point.coord(irank)/dst_step(irank);
00133 else root(irank)=0.0;
00134 }
00135 root += offset;
00136 ODINLOG(odinlog,normalDebug) << "root=" << root << STD_endl;
00137
00138 TinyVector<int,N_rank> lowindex=(root-0.5*kernel_extent)+0.5;
00139 TinyVector<int,N_rank> uppindex=(root+0.5*kernel_extent);
00140 ODINLOG(odinlog,normalDebug) << "lowindex/uppindex=" << lowindex << "/" << uppindex << STD_endl;
00141
00142
00143 TinyVector<int,N_rank> neighbours=uppindex-lowindex+1;
00144 ODINLOG(odinlog,normalDebug) << "neighbours=" << neighbours << STD_endl;
00145
00146
00147 STD_vector<STD_pair<TinyVector<int,N_rank>, float> >& dstvec=recipe[isrc];
00148 dstvec.clear();
00149 for(int ineighb=0; ineighb<product(neighbours); ineighb++) {
00150 TinyVector<int,N_rank> neighb_index=index2extent(neighbours, ineighb);
00151
00152
00153 TinyVector<int,N_rank> index=lowindex+neighb_index;
00154 bool ongrid=true;
00155 for(int i=0; i<N_rank; i++) {
00156 if(index(i)<0) ongrid=false;
00157 if(index(i)>=dst_shape(i)) ongrid=false;
00158 }
00159
00160
00161 if(ongrid) {
00162 TinyVector<float,N_rank> diff=(root-index)*dst_step;
00163 float radius=sqrt(sum(diff*diff))/(0.5*kernel_diameter);
00164 float weight=point.weight*kernel.calculate(radius);
00165 if(weight>=0.0) dstvec.push_back(STD_pair<TinyVector<int,N_rank>, float>(index,weight));
00166 }
00167 }
00168
00169
00170 for(unsigned int idst=0; idst<dstvec.size(); idst++) {
00171 weight_sum(dstvec[idst].first)+=dstvec[idst].second;
00172 }
00173
00174 }
00175
00176
00177
00178 for(unsigned int isrc=0; isrc<nsrc; isrc++) {
00179 STD_vector< STD_pair<TinyVector<int,N_rank>, float> >& dstvec=recipe[isrc];
00180 for(unsigned int idst=0; idst<dstvec.size(); idst++) {
00181 STD_pair<TinyVector<int,N_rank>, float>& weightpair=dstvec[idst];
00182 float weightsum=weight_sum(weightpair.first);
00183 if(weightsum>0.0) weightpair.second/=weightsum;
00184 }
00185 }
00186
00187 return weight_sum;
00188 }
00189
00191
00192 template <typename T, int N_rank>
00193 template<int N_rank_in>
00194 Array<T,N_rank> Gridding<T,N_rank>::operator () (const Array<T,N_rank_in>& src, unsigned int offset) const {
00195 Log<OdinData> odinlog("Gridding","()");
00196 Array<T,N_rank> result;
00197
00198 unsigned int nsrc=src.size();
00199 if((offset+nsrc)>recipe.size()) {
00200 ODINLOG(odinlog,errorLog) << "Max index of src=" << offset+nsrc << " exceeds recipe.size()=" << recipe.size() << STD_endl;
00201 return result;
00202 }
00203
00204 result.resize(shape);
00205 result=T(0);
00206
00207 for(unsigned int isrc=0; isrc<nsrc; isrc++) {
00208 const STD_vector< STD_pair<TinyVector<int,N_rank>, float> >& dstvec=recipe[offset+isrc];
00209 for(unsigned int idst=0; idst<dstvec.size(); idst++) {
00210 const STD_pair<TinyVector<int,N_rank>, float>& weightpair=dstvec[idst];
00211 result(weightpair.first) += weightpair.second * src(index2extent(src.shape(),isrc));
00212 }
00213 }
00214
00215
00216 return result;
00217 }
00218
00219
00220
00222
00226 template<typename T, int N_rank, bool OnPixelRot=false>
00227 class CoordTransformation {
00228
00229 public:
00230
00236 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);
00237
00241 Array<T,N_rank> operator () (const Array<T,N_rank>& A) const;
00242
00243 private:
00244 TinyVector<int,N_rank> shape_cache;
00245 Gridding<T,N_rank> gridder;
00246 };
00247
00249
00250 template <typename T, int N_rank, bool OnPixelRot>
00251 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)
00252 : shape_cache(shape) {
00253 Log<OdinData> odinlog("CoordTransformation","CoordTransformation");
00254
00255 int nsrc=product(shape);
00256 STD_vector<GriddingPoint<N_rank> > src_coords(nsrc);
00257 ODINLOG(odinlog,normalDebug) << "N_rank/nsrc=" << N_rank << "/" << nsrc << STD_endl;
00258
00259 TinyVector<float,N_rank> extent_half;
00260 if(OnPixelRot) extent_half=shape/2;
00261 else extent_half=0.5*(shape-1);
00262 TinyVector<int,N_rank> index;
00263 TinyVector<float,N_rank> findex;
00264 for(int isrc=0; isrc<nsrc; isrc++) {
00265 index=index2extent(shape, isrc);
00266
00267
00268 findex=index-extent_half;
00269 src_coords[isrc].coord=product(rotation,findex)+offset;
00270 }
00271 ODINLOG(odinlog,normalDebug) << "source done" << STD_endl;
00272
00273
00274 JDXfilter gridkernel;
00275 gridkernel.set_function("Gauss");
00276 gridder.init(shape, shape, src_coords, gridkernel, kernel_size);
00277 }
00278
00280
00281
00282 template <typename T, int N_rank, bool OnPixelRot>
00283 Array<T,N_rank> CoordTransformation<T,N_rank,OnPixelRot>::operator () (const Array<T,N_rank>& A) const {
00284 Log<OdinData> odinlog("CoordTransformation","()");
00285 if(A.shape()!=shape_cache) {
00286 ODINLOG(odinlog,errorLog) << "Shape mismatch" << STD_endl;
00287 return A;
00288 }
00289
00290 return gridder(A);
00291 }
00292
00293
00299 #endif