Commit a6e1eb4f authored by Martin Reinecke's avatar Martin Reinecke
Browse files

Merge branch 'wsclean_adjustments' into 'master'

Wsclean adjustments

See merge request !28
parents 38f63ce9 eb9f681c
...@@ -152,27 +152,6 @@ template<typename T, size_t ndim> const_mav<T, ndim> nullmav() ...@@ -152,27 +152,6 @@ template<typename T, size_t ndim> const_mav<T, ndim> nullmav()
shp.fill(0); shp.fill(0);
return const_mav<T, ndim>(nullptr, shp); return const_mav<T, ndim>(nullptr, shp);
} }
template<typename T, size_t ndim> class tmpStorage
{
private:
vector<T> d;
mav<T,ndim> mav_;
static size_t prod(const array<size_t,ndim> &shp)
{
size_t res=1;
for (auto v: shp) res*=v;
return res;
}
public:
tmpStorage(const array<size_t,ndim> &shp)
: d(prod(shp)), mav_(d.data(), shp) {}
mav<T,ndim> &getMav() { return mav_; }
const_mav<T,ndim> getCmav() { return cmav(mav_); }
void fill(const T & val)
{ std::fill(d.begin(), d.end(), val); }
};
// //
// basic utilities // basic utilities
...@@ -239,6 +218,28 @@ template<size_t ndim> void checkShape ...@@ -239,6 +218,28 @@ template<size_t ndim> void checkShape
template<typename T> inline T fmod1 (T v) template<typename T> inline T fmod1 (T v)
{ return v-floor(v); } { return v-floor(v); }
template<typename T, size_t ndim> class tmpStorage
{
private:
vector<T> d;
mav<T,ndim> mav_;
static size_t prod(const array<size_t,ndim> &shp)
{
size_t res=1;
for (auto v: shp) res*=v;
return res;
}
public:
tmpStorage(const array<size_t,ndim> &shp)
: d(prod(shp)), mav_(d.data(), shp) {}
mav<T,ndim> &getMav() { return mav_; }
const_mav<T,ndim> getCmav() { return cmav(mav_); }
void fill(const T & val)
{ std::fill(d.begin(), d.end(), val); }
};
// //
// Utilities for Gauss-Legendre quadrature // Utilities for Gauss-Legendre quadrature
// //
...@@ -254,8 +255,8 @@ void legendre_prep(int n, vector<double> &x, vector<double> &w, size_t nthreads) ...@@ -254,8 +255,8 @@ void legendre_prep(int n, vector<double> &x, vector<double> &w, size_t nthreads)
x.resize(m); x.resize(m);
w.resize(m); w.resize(m);
double t0 = 1 - (1-1./n) / (8.*n*n); const double t0 = 1 - (1-1./n) / (8.*n*n);
double t1 = 1./(4.*n+2.); const double t1 = 1./(4.*n+2.);
#pragma omp parallel num_threads(nthreads) #pragma omp parallel num_threads(nthreads)
{ {
...@@ -381,14 +382,17 @@ class ES_Kernel ...@@ -381,14 +382,17 @@ class ES_Kernel
size_t supp; size_t supp;
public: public:
ES_Kernel(size_t supp_, size_t nthreads) ES_Kernel(size_t supp_, double ofactor, size_t nthreads)
: beta(get_beta(supp_)*supp_), p(int(1.5*supp_+2)), supp(supp_) : beta(get_beta(supp_,ofactor)*supp_), p(int(1.5*supp_+2)), supp(supp_)
{ {
legendre_prep(2*p,x,wgt,nthreads); legendre_prep(2*p,x,wgt,nthreads);
psi=x; psi=x;
for (auto &v:psi) for (auto &v:psi)
v=operator()(v); v=operator()(v);
} }
ES_Kernel(size_t supp_, size_t nthreads)
: ES_Kernel(supp_, 2., nthreads){}
double operator()(double v) const { return exp(beta*(sqrt(1.-v*v)-1.)); } double operator()(double v) const { return exp(beta*(sqrt(1.-v*v)-1.)); }
/* Compute correction factors for the ES gridding kernel /* Compute correction factors for the ES gridding kernel
This implementation follows eqs. (3.8) to (3.10) of Barnett et al. 2018 */ This implementation follows eqs. (3.8) to (3.10) of Barnett et al. 2018 */
...@@ -399,33 +403,59 @@ class ES_Kernel ...@@ -399,33 +403,59 @@ class ES_Kernel
tmp += wgt[i]*psi[i]*cos(pi*supp*v*x[i]); tmp += wgt[i]*psi[i]*cos(pi*supp*v*x[i]);
return 1./(supp*tmp); return 1./(supp*tmp);
} }
static double get_beta(size_t supp) static double get_beta(size_t supp, double ofactor=2)
{
myassert((supp>=2) && (supp<=15), "unsupported support size");
if (ofactor>=2)
{ {
static const vector<double> opt_beta {-1, 0.14, 1.70, 2.08, 2.205, 2.26, static const vector<double> opt_beta {-1, 0.14, 1.70, 2.08, 2.205, 2.26,
2.29, 2.307, 2.316, 2.3265, 2.3324, 2.282, 2.294, 2.304, 2.3138, 2.317}; 2.29, 2.307, 2.316, 2.3265, 2.3324, 2.282, 2.294, 2.304, 2.3138, 2.317};
myassert(supp<opt_beta.size(), "bad support size"); myassert(supp<opt_beta.size(), "bad support size");
return opt_beta[supp]; return opt_beta[supp];
} }
if (ofactor>=1.2)
{
// empirical, but pretty accurate approximation
static const array<double,16> betacorr{0,0,-0.51,-0.21,-0.1,-0.05,-0.025,-0.0125,0,0,0,0,0,0,0,0};
auto x0 = 1./(2*ofactor);
auto bcstrength=1.+(x0-0.25)*2.5;
return 2.32+bcstrength*betacorr[supp]+(0.25-x0)*3.1;
}
myfail("oversampling factor is too small");
}
static size_t get_supp(double epsilon) static size_t get_supp(double epsilon, double ofactor=2)
{
double epssq = epsilon*epsilon;
if (ofactor>=2)
{ {
static const vector<double> maxmaperr { 1e8, 0.19, 2.98e-3, 5.98e-5, static const vector<double> maxmaperr { 1e8, 0.19, 2.98e-3, 5.98e-5,
1.11e-6, 2.01e-8, 3.55e-10, 5.31e-12, 8.81e-14, 1.34e-15, 2.17e-17, 1.11e-6, 2.01e-8, 3.55e-10, 5.31e-12, 8.81e-14, 1.34e-15, 2.17e-17,
2.12e-19, 2.88e-21, 3.92e-23, 8.21e-25, 7.13e-27 }; 2.12e-19, 2.88e-21, 3.92e-23, 8.21e-25, 7.13e-27 };
double epssq = epsilon*epsilon;
for (size_t i=1; i<maxmaperr.size(); ++i) for (size_t i=1; i<maxmaperr.size(); ++i)
if (epssq>maxmaperr[i]) return i; if (epssq>maxmaperr[i]) return i;
myfail("requested epsilon too small - minimum is 1e-13"); myfail("requested epsilon too small - minimum is 1e-13");
} }
if (ofactor>=1.2)
{
for (size_t w=2; w<16; ++w)
{
auto estimate = 12*exp(-2.*w*ofactor); // empirical, not very good approximation
if (epssq>estimate) return w;
}
myfail("requested epsilon too small");
}
myfail("oversampling factor is too small");
}
}; };
/* Compute correction factors for the ES gridding kernel /* Compute correction factors for the ES gridding kernel
This implementation follows eqs. (3.8) to (3.10) of Barnett et al. 2018 */ This implementation follows eqs. (3.8) to (3.10) of Barnett et al. 2018 */
vector<double> correction_factors(size_t n, size_t nval, size_t supp, vector<double> correction_factors(size_t n, double ofactor, size_t nval, size_t supp,
size_t nthreads) size_t nthreads)
{ {
ES_Kernel kernel(supp, nthreads); ES_Kernel kernel(supp, ofactor, nthreads);
vector<double> res(nval); vector<double> res(nval);
double xn = 1./n; double xn = 1./n;
#pragma omp parallel for schedule(static) num_threads(nthreads) #pragma omp parallel for schedule(static) num_threads(nthreads)
...@@ -467,7 +497,7 @@ class Baselines ...@@ -467,7 +497,7 @@ class Baselines
public: public:
template<typename T> Baselines(const const_mav<T,2> &coord_, template<typename T> Baselines(const const_mav<T,2> &coord_,
const const_mav<T,1> &freq) const const_mav<T,1> &freq, bool negate_v=false)
{ {
constexpr double speedOfLight = 299792458.; constexpr double speedOfLight = 299792458.;
myassert(coord_.shape(1)==3, "dimension mismatch"); myassert(coord_.shape(1)==3, "dimension mismatch");
...@@ -488,6 +518,10 @@ class Baselines ...@@ -488,6 +518,10 @@ class Baselines
f_over_c[i] = freq(i)/speedOfLight; f_over_c[i] = freq(i)/speedOfLight;
} }
coord.resize(nrows); coord.resize(nrows);
if (negate_v)
for (size_t i=0; i<coord.size(); ++i)
coord[i] = UVW(coord_(i,0), -coord_(i,1), coord_(i,2));
else
for (size_t i=0; i<coord.size(); ++i) for (size_t i=0; i<coord.size(); ++i)
coord[i] = UVW(coord_(i,0), coord_(i,1), coord_(i,2)); coord[i] = UVW(coord_(i,0), coord_(i,1), coord_(i,2));
} }
...@@ -550,56 +584,68 @@ class Baselines ...@@ -550,56 +584,68 @@ class Baselines
class GridderConfig class GridderConfig
{ {
protected: protected:
size_t nx_dirty, ny_dirty; size_t nx_dirty, ny_dirty, nu, nv;
double eps, psx, psy; double ofactor, eps, psx, psy;
size_t supp, nsafe, nu, nv; size_t supp, nsafe;
double beta; double beta;
vector<double> cfu, cfv; vector<double> cfu, cfv;
size_t nthreads; size_t nthreads;
double ushift, vshift; double ushift, vshift;
int maxiu0, maxiv0; int maxiu0, maxiv0;
complex<double> wscreen(double x, double y, double w, bool adjoint) const complex<double> wscreen(double x, double y, double w, bool adjoint,
bool divide_by_n) const
{ {
constexpr double pi = 3.141592653589793238462643383279502884197; constexpr double pi = 3.141592653589793238462643383279502884197;
double tmp = 1-x-y; double tmp = 1-x-y;
if (tmp<0) return 0.; if (tmp<=0) return divide_by_n ? 0. : 1.; // no phase factor beyond the horizon
double nm1 = (-x-y)/(sqrt(tmp)+1); // more accurate form of sqrt(1-x-y) double nm1 = (-x-y)/(sqrt(tmp)+1); // more accurate form of sqrt(1-x-y)-1
double n = nm1+1., xn = 1./n;
double phase = 2*pi*w*nm1; double phase = 2*pi*w*nm1;
if (adjoint) phase *= -1; if (adjoint) phase *= -1;
double xn = divide_by_n ? 1./(nm1+1) : 1;
return complex<double>(cos(phase)*xn, sin(phase)*xn); return complex<double>(cos(phase)*xn, sin(phase)*xn);
} }
public: public:
GridderConfig(size_t nxdirty, size_t nydirty, double epsilon, GridderConfig(size_t nxdirty, size_t nydirty, size_t nu_, size_t nv_,
double pixsize_x, double pixsize_y, size_t nthreads_) double epsilon, double pixsize_x, double pixsize_y, size_t nthreads_)
: nx_dirty(nxdirty), ny_dirty(nydirty), eps(epsilon), : nx_dirty(nxdirty), ny_dirty(nydirty), nu(nu_), nv(nv_),
ofactor(min(double(nu)/nxdirty, double(nv)/nydirty)),
eps(epsilon),
psx(pixsize_x), psy(pixsize_y), psx(pixsize_x), psy(pixsize_y),
supp(ES_Kernel::get_supp(epsilon)), nsafe((supp+1)/2), supp(ES_Kernel::get_supp(epsilon, ofactor)), nsafe((supp+1)/2),
nu(max(2*nsafe,2*nx_dirty)), nv(max(2*nsafe,2*ny_dirty)), beta(ES_Kernel::get_beta(supp, ofactor)*supp),
beta(ES_Kernel::get_beta(supp)*supp),
cfu(nx_dirty), cfv(ny_dirty), nthreads(nthreads_), cfu(nx_dirty), cfv(ny_dirty), nthreads(nthreads_),
ushift(supp*(-0.5)+1+nu), vshift(supp*(-0.5)+1+nv), ushift(supp*(-0.5)+1+nu), vshift(supp*(-0.5)+1+nv),
maxiu0((nu+nsafe)-supp), maxiv0((nv+nsafe)-supp) maxiu0((nu+nsafe)-supp), maxiv0((nv+nsafe)-supp)
{ {
myassert(nu>=2*nsafe, "nu too small");
myassert(nv>=2*nsafe, "nv too small");
myassert((nx_dirty&1)==0, "nx_dirty must be even"); myassert((nx_dirty&1)==0, "nx_dirty must be even");
myassert((ny_dirty&1)==0, "ny_dirty must be even"); myassert((ny_dirty&1)==0, "ny_dirty must be even");
myassert((nu&1)==0, "nu must be even");
myassert((nv&1)==0, "nv must be even");
myassert(epsilon>0, "epsilon must be positive"); myassert(epsilon>0, "epsilon must be positive");
myassert(pixsize_x>0, "pixsize_x must be positive"); myassert(pixsize_x>0, "pixsize_x must be positive");
myassert(pixsize_y>0, "pixsize_y must be positive"); myassert(pixsize_y>0, "pixsize_y must be positive");
myassert(ofactor>=1.2, "oversampling factor smaller than 1.2");
auto tmp = correction_factors(nu, nx_dirty/2+1, supp, nthreads); auto tmp = correction_factors(nu, ofactor, nx_dirty/2+1, supp, nthreads);
cfu[nx_dirty/2]=tmp[0]; cfu[nx_dirty/2]=tmp[0];
cfu[0]=tmp[nx_dirty/2]; cfu[0]=tmp[nx_dirty/2];
for (size_t i=1; i<nx_dirty/2; ++i) for (size_t i=1; i<nx_dirty/2; ++i)
cfu[nx_dirty/2-i] = cfu[nx_dirty/2+i] = tmp[i]; cfu[nx_dirty/2-i] = cfu[nx_dirty/2+i] = tmp[i];
tmp = correction_factors(nv, ny_dirty/2+1, supp, nthreads); tmp = correction_factors(nv, ofactor, ny_dirty/2+1, supp, nthreads);
cfv[ny_dirty/2]=tmp[0]; cfv[ny_dirty/2]=tmp[0];
cfv[0]=tmp[ny_dirty/2]; cfv[0]=tmp[ny_dirty/2];
for (size_t i=1; i<ny_dirty/2; ++i) for (size_t i=1; i<ny_dirty/2; ++i)
cfv[ny_dirty/2-i] = cfv[ny_dirty/2+i] = tmp[i]; cfv[ny_dirty/2-i] = cfv[ny_dirty/2+i] = tmp[i];
} }
GridderConfig(size_t nxdirty, size_t nydirty,
double epsilon, double pixsize_x, double pixsize_y, size_t nthreads_)
: GridderConfig(nxdirty, nydirty, max<size_t>(30,2*nxdirty),
max<size_t>(30,2*nydirty), epsilon, pixsize_x,
pixsize_y, nthreads_) {}
size_t Nxdirty() const { return nx_dirty; } size_t Nxdirty() const { return nx_dirty; }
size_t Nydirty() const { return ny_dirty; } size_t Nydirty() const { return ny_dirty; }
double Epsilon() const { return eps; } double Epsilon() const { return eps; }
...@@ -611,6 +657,7 @@ class GridderConfig ...@@ -611,6 +657,7 @@ class GridderConfig
size_t Nsafe() const { return nsafe; } size_t Nsafe() const { return nsafe; }
double Beta() const { return beta; } double Beta() const { return beta; }
size_t Nthreads() const { return nthreads; } size_t Nthreads() const { return nthreads; }
double Ofactor() const{ return ofactor; }
template<typename T> void apply_taper(const mav<const T,2> &img, mav<T,2> &img2, bool divide) const template<typename T> void apply_taper(const mav<const T,2> &img, mav<T,2> &img2, bool divide) const
{ {
...@@ -716,10 +763,47 @@ class GridderConfig ...@@ -716,10 +763,47 @@ class GridderConfig
} }
template<typename T> void apply_wscreen(const const_mav<complex<T>,2> &dirty, template<typename T> void apply_wscreen(const const_mav<complex<T>,2> &dirty,
mav<complex<T>,2> &dirty2, double w, bool adjoint) const mav<complex<T>,2> &dirty2, double w, bool adjoint, bool divide_by_n) const
{ {
checkShape(dirty.shape(), {nx_dirty, ny_dirty}); checkShape(dirty.shape(), {nx_dirty, ny_dirty});
checkShape(dirty2.shape(), {nx_dirty, ny_dirty}); checkShape(dirty2.shape(), {nx_dirty, ny_dirty});
#if 0
if ((nx_dirty==ny_dirty) && (psx==psy)) // extra symmetry
{
double p0 = -0.5*nx_dirty*psx;
#pragma omp parallel for num_threads(nthreads) schedule(dynamic,10)
for (size_t i=0; i<=nx_dirty/2; ++i)
{
double fx = p0+i*psx;
fx *= fx;
for (size_t j=0; j<=i; ++j)
{
double fy = p0+j*psy;
auto ws = complex<T>(wscreen(fx, fy*fy, w, adjoint, divide_by_n));
dirty2(i,j) = dirty(i,j)*ws; // lower left
if (j!=i) dirty2(j,i) = dirty(j,i)*ws; // lower left
size_t i2 = nx_dirty-i, j2 = ny_dirty-j;
if ((i>0)&&(i<i2))
{
dirty2(i2,j) = dirty(i2,j)*ws; // lower right
if (i!=j) dirty2(j,i2) = dirty(j,i2)*ws; // lower right
if ((j>0)&&(j<j2))
{
dirty2(i2,j2) = dirty(i2,j2)*ws; // upper right
if (i!=j) dirty2(j2,i2) = dirty(j2,i2)*ws; // upper right
}
}
if ((j>0)&&(j<j2))
{
dirty2(i,j2) = dirty(i,j2)*ws; // upper left
if (i!=j) dirty2(j2,i) = dirty(j2,i)*ws; // upper left
}
}
}
}
else
#endif
{
double x0 = -0.5*nx_dirty*psx, double x0 = -0.5*nx_dirty*psx,
y0 = -0.5*ny_dirty*psy; y0 = -0.5*ny_dirty*psy;
#pragma omp parallel for num_threads(nthreads) schedule(static) #pragma omp parallel for num_threads(nthreads) schedule(static)
...@@ -730,7 +814,7 @@ class GridderConfig ...@@ -730,7 +814,7 @@ class GridderConfig
for (size_t j=0; j<=ny_dirty/2; ++j) for (size_t j=0; j<=ny_dirty/2; ++j)
{ {
double fy = y0+j*psy; double fy = y0+j*psy;
auto ws = complex<T>(wscreen(fx, fy*fy, w, adjoint)); auto ws = complex<T>(wscreen(fx, fy*fy, w, adjoint, divide_by_n));
dirty2(i,j) = dirty(i,j)*ws; // lower left dirty2(i,j) = dirty(i,j)*ws; // lower left
size_t i2 = nx_dirty-i, j2 = ny_dirty-j; size_t i2 = nx_dirty-i, j2 = ny_dirty-j;
if ((i>0)&&(i<i2)) if ((i>0)&&(i<i2))
...@@ -744,6 +828,7 @@ class GridderConfig ...@@ -744,6 +828,7 @@ class GridderConfig
} }
} }
} }
}
}; };
constexpr int logsquare=4; constexpr int logsquare=4;
...@@ -803,8 +888,6 @@ template<typename T, typename T2=complex<T>> class Helper ...@@ -803,8 +888,6 @@ template<typename T, typename T2=complex<T>> class Helper
{ {
if (bu0<-nsafe) return; // nothing written into buffer yet if (bu0<-nsafe) return; // nothing written into buffer yet
#pragma omp critical (gridder_writing_to_grid)
{
int idxu = (bu0+nu)%nu; int idxu = (bu0+nu)%nu;
int idxv0 = (bv0+nv)%nv; int idxv0 = (bv0+nv)%nv;
for (int iu=0; iu<su; ++iu) for (int iu=0; iu<su; ++iu)
...@@ -819,7 +902,6 @@ template<typename T, typename T2=complex<T>> class Helper ...@@ -819,7 +902,6 @@ template<typename T, typename T2=complex<T>> class Helper
locks[idxu].unlock(); locks[idxu].unlock();
if (++idxu>=nu) idxu=0; if (++idxu>=nu) idxu=0;
} }
}
} }
void load() void load()
...@@ -1279,8 +1361,13 @@ template<typename T> void apply_wcorr(const GridderConfig &gconf, ...@@ -1279,8 +1361,13 @@ template<typename T> void apply_wcorr(const GridderConfig &gconf,
double tmp = 1.-fx-fy; double tmp = 1.-fx-fy;
if (tmp>=0) if (tmp>=0)
{ {
auto nm1 = (-fx-fy)/(sqrt(1.-fx-fy)+1.); // accurate form of sqrt(1-x-y) auto nm1 = (-fx-fy)/(sqrt(tmp)+1.); // accurate form of sqrt(1-x-y)-1
fct = T((nm1<=-1) ? 0. : kernel.corfac(nm1*dw)); fct = T(kernel.corfac(nm1*dw));
}
else // beyond the horizon, don't really know what to do here
{
double nm1 = sqrt(-tmp)-1;
fct = T(kernel.corfac(nm1*dw));
} }
size_t i2 = nx_dirty-i, j2 = ny_dirty-j; size_t i2 = nx_dirty-i, j2 = ny_dirty-j;
dirty(i,j)*=fct; dirty(i,j)*=fct;
...@@ -1367,9 +1454,12 @@ template<typename Serv> class WgridHelper ...@@ -1367,9 +1454,12 @@ template<typename Serv> class WgridHelper
if (verbosity>0) cout << "Using single-threaded mode" << endl; if (verbosity>0) cout << "Using single-threaded mode" << endl;
#endif #endif
if (verbosity>0) cout << "W range: " << wmin << " to " << wmax << endl; if (verbosity>0) cout << "W range: " << wmin << " to " << wmax << endl;
double x0 = -0.5*gconf.Nxdirty()*gconf.Pixsize_x(), double x0 = -0.5*gconf.Nxdirty()*gconf.Pixsize_x(),
y0 = -0.5*gconf.Nydirty()*gconf.Pixsize_y(); y0 = -0.5*gconf.Nydirty()*gconf.Pixsize_y();
double nmin = sqrt(max(1.-x0*x0-y0*y0,0.))-1.; double nmin = sqrt(max(1.-x0*x0-y0*y0,0.))-1.;
if (x0*x0+y0*y0>1.)
nmin = -sqrt(abs(1.-x0*x0-y0*y0))-1.;
dw = 0.25/abs(nmin); dw = 0.25/abs(nmin);
nplanes = size_t((wmax-wmin)/dw+2); nplanes = size_t((wmax-wmin)/dw+2);
dw = (1.+1e-13)*(wmax-wmin)/(nplanes-1); dw = (1.+1e-13)*(wmax-wmin)/(nplanes-1);
...@@ -1382,6 +1472,15 @@ template<typename Serv> class WgridHelper ...@@ -1382,6 +1472,15 @@ template<typename Serv> class WgridHelper
if (verbosity>0) cout << "nplanes: " << nplanes << endl; if (verbosity>0) cout << "nplanes: " << nplanes << endl;
minplane.resize(nplanes); minplane.resize(nplanes);
#if 0
// extra short, but potentially inefficient version:
for (size_t ipart=0; ipart<nvis; ++ipart)
{
int plane0 = max(0,int(1+(abs(srv.getCoord(ipart).w)-(0.5*supp*dw)-wmin)/dw));
minplane[plane0].push_back(idx_t(ipart));
}
#else
// full fledged, overdesigned OpenMP version
vector<size_t> tcnt(max<int>(nthreads, my_max_threads())*nplanes,0); vector<size_t> tcnt(max<int>(nthreads, my_max_threads())*nplanes,0);
#pragma omp parallel num_threads(nthreads) #pragma omp parallel num_threads(nthreads)
{ {
...@@ -1417,6 +1516,7 @@ template<typename Serv> class WgridHelper ...@@ -1417,6 +1516,7 @@ template<typename Serv> class WgridHelper
minplane[plane0][myofs[plane0]++]=idx_t(ipart); minplane[plane0][myofs[plane0]++]=idx_t(ipart);
} }
} }
#endif
} }
typename Serv::Tsub getSubserv() const typename Serv::Tsub getSubserv() const
...@@ -1459,14 +1559,14 @@ template<typename T, typename Serv> void x2dirty( ...@@ -1459,14 +1559,14 @@ template<typename T, typename Serv> void x2dirty(
grid.fill(0); grid.fill(0);
x2grid_c(gconf, hlp.getSubserv(), grid, hlp.W(), dw); x2grid_c(gconf, hlp.getSubserv(), grid, hlp.W(), dw);
gconf.grid2dirty_c_overwrite(grid, tdirty); gconf.grid2dirty_c_overwrite(grid, tdirty);
gconf.apply_wscreen(cmav(tdirty), tdirty, hlp.W(), true); gconf.apply_wscreen(cmav(tdirty), tdirty, hlp.W(), true, true);
#pragma omp parallel for num_threads(nthreads) #pragma omp parallel for num_threads(nthreads)
for (size_t i=0; i<gconf.Nxdirty(); ++i) for (size_t i=0; i<gconf.Nxdirty(); ++i)
for (size_t j=0; j<gconf.Nydirty(); ++j) for (size_t j=0; j<gconf.Nydirty(); ++j)
dirty(i,j) += tdirty(i,j).real(); dirty(i,j) += tdirty(i,j).real();
} }
// correct for w gridding // correct for w gridding
apply_wcorr(gconf, dirty, ES_Kernel(gconf.Supp(), nthreads), dw); apply_wcorr(gconf, dirty, ES_Kernel(gconf.Supp(), gconf.Ofactor(), nthreads), dw);
} }
else else
{ {
...@@ -1511,7 +1611,7 @@ template<typename T, typename Serv> void dirty2x( ...@@ -1511,7 +1611,7 @@ template<typename T, typename Serv> void dirty2x(
for (size_t j=0; j<ny_dirty; ++j) for (size_t j=0; j<ny_dirty; ++j)
tdirty(i,j) = dirty(i,j); tdirty(i,j) = dirty(i,j);
// correct for w gridding // correct for w gridding
apply_wcorr(gconf, tdirty, ES_Kernel(gconf.Supp(), nthreads), dw); apply_wcorr(gconf, tdirty, ES_Kernel(gconf.Supp(), gconf.Ofactor(), nthreads), dw);
tmpStorage<complex<T>,2> grid_({gconf.Nu(),gconf.Nv()}); tmpStorage<complex<T>,2> grid_({gconf.Nu(),gconf.Nv()});
auto grid=grid_.getMav(); auto grid=grid_.getMav();
tmpStorage<complex<T>,2> tdirty2_({nx_dirty, ny_dirty}); tmpStorage<complex<T>,2> tdirty2_({nx_dirty, ny_dirty});
...@@ -1524,7 +1624,7 @@ template<typename T, typename Serv> void dirty2x( ...@@ -1524,7 +1624,7 @@ template<typename T, typename Serv> void dirty2x(
for (size_t i=0; i<nx_dirty; ++i) for (size_t i=0; i<nx_dirty; ++i)
for (size_t j=0; j<ny_dirty; ++j) for (size_t j=0; j<ny_dirty; ++j)
tdirty2(i,j) = tdirty(i,j); tdirty2(i,j) = tdirty(i,j);
gconf.apply_wscreen(cmav(tdirty2), tdirty2, hlp.W(), false); gconf.apply_wscreen(cmav(tdirty2), tdirty2, hlp.W(), false, true);
gconf.dirty2grid_c(cmav(tdirty2), grid); gconf.dirty2grid_c(cmav(tdirty2), grid);
grid2x_c(gconf, cmav(grid), hlp.getSubserv(), hlp.W(), dw); grid2x_c(gconf, cmav(grid), hlp.getSubserv(), hlp.W(), dw);
...@@ -1619,7 +1719,7 @@ void fillIdx(const Baselines &baselines, ...@@ -1619,7 +1719,7 @@ void fillIdx(const Baselines &baselines,
size_t lo, hi; size_t lo, hi;
calc_share(nthr, id, nrow, lo, hi); calc_share(nthr, id, nrow, lo, hi);
vector<idx_t> &lacc(acc[id]); vector<idx_t> &lacc(acc[id]);
lacc.resize(nbu*nbv+1, 0); lacc.assign(nbu*nbv+1, 0);
for (idx_t irow=lo, idx=lo*(chend-chbegin); irow<hi; ++irow) for (idx_t irow=lo, idx=lo*(chend-chbegin); irow<hi; ++irow)
for (int ichan=chbegin; ichan<chend; ++ichan, ++idx) for (int ichan=chbegin; ichan<chend; ++ichan, ++idx)
...@@ -1666,13 +1766,16 @@ void fillIdx(const Baselines &baselines, ...@@ -1666,13 +1766,16 @@ void fillIdx(const Baselines &baselines,
} }