Commit 8ea2dd13 authored by Martin Reinecke's avatar Martin Reinecke
Browse files

make interface a bit more flexible

parent 089b6fc8
......@@ -131,7 +131,7 @@ template<typename T>
template<typename T>
using pyarr_c = py::array_t<T, py::array::c_style | py::array::forcecast>;
template<typename T> pyarr_c<T> makearray(const vector<size_t> &shape)
template<typename T> pyarr_c<T> makeArray(const vector<size_t> &shape)
{ return pyarr_c<T>(shape); }
size_t get_w(double epsilon)
......@@ -165,6 +165,23 @@ void checkArray(const py::array &arr, const char *aname,
}
}
template<typename T> pyarr_c<T> provideArray(py::object &in,
const vector<size_t> &shape)
{
if (in.is(py::none()))
{
auto tmp_ = makeArray<T>(shape);
size_t sz = size_t(tmp_.size());
auto tmp = tmp_.mutable_data();
for (size_t i=0; i<sz; ++i)
tmp[i] = T(0);
return tmp_;
}
auto tmp_ = in.cast<pyarr_c<T>>();
checkArray(tmp_, "temporary", shape);
return tmp_;
}
template<typename T> pyarr_c<T> complex2hartley
(const pyarr_c<complex<T>> &grid_)
{
......@@ -172,7 +189,7 @@ template<typename T> pyarr_c<T> complex2hartley
size_t nu = size_t(grid_.shape(0)), nv = size_t(grid_.shape(1));
auto grid = grid_.data();
auto res = makearray<T>({nu,nv});
auto res = makeArray<T>({nu,nv});
auto grid2 = res.mutable_data();
#pragma omp parallel for
for (size_t u=0; u<nu; ++u)
......@@ -197,7 +214,7 @@ template<typename T> pyarr_c<complex<T>> hartley2complex
size_t nu = size_t(grid_.shape(0)), nv = size_t(grid_.shape(1));
auto grid = grid_.data();
auto res=makearray<complex<T>>({nu, nv});
auto res=makeArray<complex<T>>({nu, nv});
auto grid2 = res.mutable_data();
#pragma omp parallel for
for (size_t u=0; u<nu; ++u)
......@@ -317,7 +334,7 @@ template<typename T> class Baselines
auto idx = idx_.data();
auto ms = ms_.data();
auto res=makearray<T2>({nvis});
auto res=makeArray<T2>({nvis});
auto vis = res.mutable_data();
#pragma omp parallel for
for (size_t i=0; i<nvis; ++i)
......@@ -326,7 +343,7 @@ template<typename T> class Baselines
}
template<typename T2> pyarr_c<T2> vis2ms(const pyarr_c<T2> &vis_,
const pyarr_c<uint32_t> &idx_) const
const pyarr_c<uint32_t> &idx_, py::object &ms_in) const
{
checkArray(vis_, "vis", {0});
size_t nvis = size_t(vis_.shape(0));
......@@ -334,32 +351,13 @@ template<typename T> class Baselines
auto idx = idx_.data();
auto vis = vis_.data();
auto res = makearray<T2>({nrows, nchan});
auto res = provideArray<T2>(ms_in, {nrows, nchan});
auto ms = res.mutable_data();
for (size_t i=0; i<nrows*nchan; ++i)
ms[i] = T2(0);
#pragma omp parallel for
for (size_t i=0; i<nvis; ++i)
ms[idx[i]] = vis[i];
return res;
}
template<typename T2> pyarr_c<T2> add_vis_to_ms(const pyarr_c<T2> &vis_,
const pyarr_c<uint32_t> &idx_, pyarr_c<T2> &ms_) const
{
checkArray(vis_, "vis", {0});
size_t nvis = size_t(vis_.shape(0));
checkArray(idx_, "idx", {nvis});
checkArray(ms_, "ms", {nrows, nchan});
auto idx = idx_.data();
auto vis = vis_.data();
auto ms = ms_.mutable_data();
#pragma omp parallel for
for (size_t i=0; i<nvis; ++i)
ms[idx[i]] += vis[i];
return ms_;
}
};
constexpr int logsquare=4;
......@@ -408,10 +406,10 @@ template<typename T> class GridderConfig
pyarr_c<T> grid2dirty(const pyarr_c<T> &grid) const
{
checkArray(grid, "grid", {nu, nv});
auto tmp = makearray<T>({nu, nv});
auto tmp = makeArray<T>({nu, nv});
auto ptmp = tmp.mutable_data();
hartley2_2D<T>(grid, tmp);
auto res = makearray<T>({nx_dirty, ny_dirty});
auto res = makeArray<T>({nx_dirty, ny_dirty});
auto pout = res.mutable_data();
for (size_t i=0; i<nx_dirty; ++i)
for (size_t j=0; j<ny_dirty; ++j)
......@@ -427,12 +425,12 @@ template<typename T> class GridderConfig
pyarr_c<complex<T>> grid2dirty_c(const pyarr_c<complex<T>> &grid) const
{
checkArray(grid, "grid", {nu, nv});
auto tmp = makearray<complex<T>>({nu, nv});
auto tmp = makeArray<complex<T>>({nu, nv});
auto ptmp = tmp.mutable_data();
pocketfft::c2c({nu,nv},{grid.strides(0),grid.strides(1)},
{tmp.strides(0), tmp.strides(1)}, {0,1}, pocketfft::BACKWARD,
grid.data(), tmp.mutable_data(), T(1), 0);
auto res = makearray<complex<T>>({nx_dirty, ny_dirty});
auto res = makeArray<complex<T>>({nx_dirty, ny_dirty});
auto pout = res.mutable_data();
for (size_t i=0; i<nx_dirty; ++i)
for (size_t j=0; j<ny_dirty; ++j)
......@@ -449,7 +447,7 @@ template<typename T> class GridderConfig
{
checkArray(dirty, "dirty", {nx_dirty, ny_dirty});
auto pdirty = dirty.data();
auto tmp = makearray<T>({nu, nv});
auto tmp = makeArray<T>({nu, nv});
auto ptmp = tmp.mutable_data();
for (size_t i=0; i<nu*nv; ++i)
ptmp[i] = 0.;
......@@ -469,7 +467,7 @@ template<typename T> class GridderConfig
{
checkArray(dirty, "dirty", {nx_dirty, ny_dirty});
auto pdirty = dirty.data();
auto tmp = makearray<complex<T>>({nu, nv});
auto tmp = makeArray<complex<T>>({nu, nv});
auto ptmp = tmp.mutable_data();
for (size_t i=0; i<nu*nv; ++i)
ptmp[i] = 0.;
......@@ -519,7 +517,7 @@ template<typename T> class Helper
{
if (bu0<-nsafe) return; // nothing written into buffer yet
#pragma omp critical
#pragma omp critical (gridder_writing_to_grid)
{
int idxu = (bu0+nu)%nu;
int idxv0 = (bv0+nv)%nv;
......@@ -604,7 +602,7 @@ template<typename T> pyarr_c<complex<T>> vis2grid_c(const Baselines<T> &baseline
auto idx = idx_.data();
size_t nu=gconf.Nu(), nv=gconf.Nv();
auto res = makearray<complex<T>>({nu, nv});
auto res = makeArray<complex<T>>({nu, nv});
auto grid = res.mutable_data();
for (size_t i=0; i<nu*nv; ++i) grid[i] = 0.;
T beta = gconf.Beta();
......@@ -642,6 +640,57 @@ template<typename T> pyarr_c<T> vis2grid(const Baselines<T> &baselines,
const pyarr_c<complex<T>> &vis_)
{ return complex2hartley(vis2grid_c(baselines, gconf, idx_, vis_)); }
template<typename T> pyarr_c<complex<T>> ms2grid_c(const Baselines<T> &baselines,
const GridderConfig<T> &gconf, const pyarr_c<uint32_t> &idx_,
const pyarr_c<complex<T>> &ms_)
{
auto nrows = baselines.Nrows();
auto nchan = baselines.Nchannels();
checkArray(ms_, "ms", {nrows, nchan});
checkArray(idx_, "idx", {0});
size_t nvis = size_t(idx_.shape(0));
auto ms = ms_.data();
auto idx = idx_.data();
size_t nu=gconf.Nu(), nv=gconf.Nv();
auto res = makeArray<complex<T>>({nu, nv});
auto grid = res.mutable_data();
for (size_t i=0; i<nu*nv; ++i) grid[i] = 0.;
T beta = gconf.Beta();
size_t w = gconf.W();
#pragma omp parallel
{
Helper<T> hlp(gconf, grid, true);
T emb = exp(-2*beta);
const T * RESTRICT ku = hlp.kernel.data();
const T * RESTRICT kv = hlp.kernel.data()+w;
// Loop over sampling points
#pragma omp for schedule(guided,100)
for (size_t ipart=0; ipart<nvis; ++ipart)
{
UVW<T> coord = baselines.effectiveCoord(idx[ipart]);
hlp.prep(coord.u, coord.v);
auto * RESTRICT ptr = hlp.p0;
auto v(ms[idx[ipart]]*emb);
for (size_t cu=0; cu<w; ++cu)
{
complex<T> tmp(v*ku[cu]);
for (size_t cv=0; cv<w; ++cv)
ptr[cv] += tmp*kv[cv];
ptr+=hlp.sv;
}
}
} // end of parallel region
return res;
}
template<typename T> pyarr_c<T> ms2grid(const Baselines<T> &baselines,
const GridderConfig<T> &gconf, const pyarr_c<uint32_t> &idx_,
const pyarr_c<complex<T>> &ms_)
{ return complex2hartley(ms2grid_c(baselines, gconf, idx_, ms_)); }
template<typename T> pyarr_c<complex<T>> grid2vis_c(const Baselines<T> &baselines,
const GridderConfig<T> &gconf, const pyarr_c<uint32_t> &idx_,
const pyarr_c<complex<T>> &grid_)
......@@ -653,7 +702,7 @@ template<typename T> pyarr_c<complex<T>> grid2vis_c(const Baselines<T> &baseline
size_t nvis = size_t(idx_.shape(0));
auto idx = idx_.data();
auto res = makearray<complex<T>>({nvis});
auto res = makeArray<complex<T>>({nvis});
auto vis = res.mutable_data();
T beta = gconf.Beta();
size_t w = gconf.W();
......@@ -692,6 +741,57 @@ template<typename T> pyarr_c<complex<T>> grid2vis(const Baselines<T> &baselines,
const pyarr_c<T> &grid_)
{ return grid2vis_c(baselines, gconf, idx_, hartley2complex(grid_)); }
template<typename T> pyarr_c<complex<T>> grid2ms_c(const Baselines<T> &baselines,
const GridderConfig<T> &gconf, const pyarr_c<uint32_t> &idx_,
const pyarr_c<complex<T>> &grid_, py::object &ms_in)
{
size_t nu=gconf.Nu(), nv=gconf.Nv();
checkArray(idx_, "idx", {0});
auto grid = grid_.data();
checkArray(grid_, "grid", {nu, nv});
size_t nvis = size_t(idx_.shape(0));
auto idx = idx_.data();
auto res = provideArray<complex<T>>(ms_in,
{baselines.Nrows(), baselines.Nchannels()});
auto ms = res.mutable_data();
T beta = gconf.Beta();
size_t w = gconf.W();
// Loop over sampling points
#pragma omp parallel
{
Helper<T> hlp(gconf, grid, false);
T emb = exp(-2*beta);
const T * RESTRICT ku = hlp.kernel.data();
const T * RESTRICT kv = hlp.kernel.data()+w;
#pragma omp for schedule(guided,100)
for (size_t ipart=0; ipart<nvis; ++ipart)
{
UVW<T> coord = baselines.effectiveCoord(idx[ipart]);
hlp.prep(coord.u, coord.v);
complex<T> r = 0;
auto * RESTRICT ptr = hlp.p0;
for (size_t cu=0; cu<w; ++cu)
{
complex<T> tmp(0);
for (size_t cv=0; cv<w; ++cv)
tmp += ptr[cv] * kv[cv];
r += tmp*ku[cu];
ptr += hlp.sv;
}
ms[idx[ipart]] += r*emb;
}
}
return res;
}
template<typename T> pyarr_c<complex<T>> grid2ms(const Baselines<T> &baselines,
const GridderConfig<T> &gconf, const pyarr_c<uint32_t> &idx_,
const pyarr_c<T> &grid_, py::object &ms_in)
{ return grid2ms_c(baselines, gconf, idx_, hartley2complex(grid_), ms_in); }
template<typename T> pyarr_c<uint32_t> getIndices(const Baselines<T> &baselines,
const GridderConfig<T> &gconf, const pyarr_c<bool> &flags_, int chbegin,
int chend, T wmin, T wmax)
......@@ -727,7 +827,7 @@ template<typename T> pyarr_c<uint32_t> getIndices(const Baselines<T> &baselines,
for (size_t i=1; i<acc.size(); ++i)
acc[i] += acc[i-1];
auto res = makearray<uint32_t>({acc.back()});
auto res = makeArray<uint32_t>({acc.back()});
auto iout = res.mutable_data();
for (size_t irow=0, idx=0; irow<nrow; ++irow)
for (int ichan=chbegin; ichan<chend; ++ichan)
......@@ -783,24 +883,6 @@ np.array((nrows, nchannels), dtype=np.complex)
the measurement set's visibility data (0 where not covered by idx)
)""";
const char *BL_add_vis_to_ms_DS = R"""(
Adds a set of visibilities to an existing MS.
Parameters
==========
vis: np.array((nvis,), dtype=np.complex)
The visibility data for the index array
idx: np.array((nvis,), dtype=np.uint32)
the indices to be inserted
ms: np.array((nrows, nchannels), dtype=np.complex)
a MS
Returns
=======
np.array((nrows, nchannels), dtype=np.complex)
the updated MS
)""";
const char *GridderConfig_DS = R"""(
Class storing information related to the gridding/degridding process.
......@@ -928,10 +1010,7 @@ PYBIND11_MODULE(nifty_gridder, m)
.def ("Nrows",&Baselines<double>::Nrows)
.def ("Nchannels",&Baselines<double>::Nchannels)
.def ("ms2vis",&Baselines<double>::ms2vis<complex<double>>, BL_ms2vis_DS, "ms"_a, "idx"_a)
// .def ("ms2vis_f32",&Baselines<double>::ms2vis<float>, "ms"_a, "idx"_a)
.def ("vis2ms",&Baselines<double>::vis2ms<complex<double>>, BL_vis2ms_DS, "vis"_a, "idx"_a)
.def ("add_vis_to_ms",&Baselines<double>::add_vis_to_ms<complex<double>>, BL_add_vis_to_ms_DS,
"vis"_a, "idx"_a, "ms"_a.noconvert());
.def ("vis2ms",&Baselines<double>::vis2ms<complex<double>>, BL_vis2ms_DS, "vis"_a, "idx"_a, "ms_in"_a=py::none());
py::class_<GridderConfig<double>> (m, "GridderConfig", GridderConfig_DS)
.def(py::init<size_t, size_t, double, double, double>(),"nxdirty"_a,
"nydirty"_a, "epsilon"_a, "urange"_a, "vrange"_a)
......@@ -944,30 +1023,11 @@ PYBIND11_MODULE(nifty_gridder, m)
m.def("getIndices", getIndices<double>, getIndices_DS, "baselines"_a, "gconf"_a,
"flags"_a, "chbegin"_a=-1, "chend"_a=-1, "wmin"_a=-1e30, "wmax"_a=1e30);
m.def("vis2grid",&vis2grid<double>, vis2grid_DS, "baselines"_a, "gconf"_a, "idx"_a, "vis"_a);
m.def("ms2grid",&ms2grid<double>, "baselines"_a, "gconf"_a, "idx"_a, "ms"_a);
m.def("grid2vis",&grid2vis<double>, grid2vis_DS, "baselines"_a, "gconf"_a, "idx"_a, "grid"_a);
m.def("grid2ms",&grid2ms<double>, "baselines"_a, "gconf"_a, "idx"_a, "grid"_a, "ms_in"_a=py::none());
m.def("vis2grid_c",&vis2grid_c<double>, "baselines"_a, "gconf"_a, "idx"_a, "vis"_a);
m.def("ms2grid_c",&ms2grid_c<double>, "baselines"_a, "gconf"_a, "idx"_a, "ms"_a);
m.def("grid2vis_c",&grid2vis_c<double>, "baselines"_a, "gconf"_a, "idx"_a, "grid"_a);
#if 0
py::class_<Baselines<float>> (m, "Baselines_f", Baselines_DS)
.def(py::init<const pyarr_c<float> &, const pyarr_c<float> &>(),
"coord"_a, "scaling"_a)
.def ("Nrows",&Baselines<float>::Nrows)
.def ("Nchannels",&Baselines<float>::Nchannels)
.def ("ms2vis",&Baselines<float>::ms2vis<complex<float>>, BL_ms2vis_DS, "ms"_a, "idx"_a)
.def ("vis2ms",&Baselines<float>::vis2ms<complex<float>>, BL_vis2ms_DS, "vis"_a, "idx"_a)
.def ("add_vis_to_ms",&Baselines<float>::add_vis_to_ms<complex<float>>, BL_add_vis_to_ms_DS,
"vis"_a, "idx"_a, "ms"_a.noconvert());
py::class_<GridderConfig<float>> (m, "GridderConfig_f")
.def(py::init<size_t, size_t, float, float, float>(),"nxdirty"_a,
"nydirty"_a, "epsilon"_a, "urange"_a, "vrange"_a)
.def("Nu", &GridderConfig<float>::Nu)
.def("Nv", &GridderConfig<float>::Nv)
.def("grid2dirty", &GridderConfig<float>::grid2dirty, "grid"_a)
.def("dirty2grid", &GridderConfig<float>::dirty2grid, "dirty"_a);
m.def("getIndices_f", getIndices<float>, "baselines"_a, "gconf"_a,
"flags"_a, "chbegin"_a=-1, "chend"_a=-1, "wmin"_a=-1e30, "wmax"_a=1e30);
m.def("vis2grid_f",&vis2grid<float>, "baselines"_a, "gconf"_a, "idx"_a, "vis"_a);
m.def("grid2vis_f",&grid2vis<float>, "baselines"_a, "gconf"_a, "idx"_a, "grid"_a);
#endif
m.def("grid2ms_c",&grid2ms_c<double>, "baselines"_a, "gconf"_a, "idx"_a, "grid"_a, "ms_in"_a=py::none());
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment