Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ift
nifty_gridder
Commits
ce4b57cf
Commit
ce4b57cf
authored
Sep 06, 2019
by
Martin Reinecke
Browse files
merge
parents
3502ad2f
d02f825f
Changes
3
Hide whitespace changes
Inline
Side-by-side
gridder_cxx.h
View file @
ce4b57cf
...
...
@@ -619,6 +619,8 @@ class GridderConfig
if
(
i2
>=
nu
)
i2
-=
nu
;
size_t
j2
=
nv
-
ny_dirty
/
2
+
j
;
if
(
j2
>=
nv
)
j2
-=
nv
;
// FIXME: for some reason g++ warns about double-to-float conversion
// here, even though there is an explicit cast...
dirty
(
i
,
j
)
=
tmav
(
i2
,
j2
)
*
T
(
cfu
[
i
]
*
cfv
[
j
]);
}
}
...
...
@@ -656,6 +658,8 @@ class GridderConfig
if
(
i2
>=
nu
)
i2
-=
nu
;
size_t
j2
=
nv
-
ny_dirty
/
2
+
j
;
if
(
j2
>=
nv
)
j2
-=
nv
;
// FIXME: for some reason g++ warns about double-to-float conversion
// here, even though there is an explicit cast...
grid
(
i2
,
j2
)
=
dirty
(
i
,
j
)
*
T
(
cfu
[
i
]
*
cfv
[
j
]);
}
}
...
...
@@ -676,7 +680,7 @@ class GridderConfig
grid
.
data
(),
grid
.
data
(),
T
(
1
),
nthreads
);
}
template
<
typename
T
>
void
getpix
(
T
u_in
,
T
v_in
,
T
&
u
,
T
&
v
,
int
&
iu0
,
int
&
iv0
)
const
void
getpix
(
double
u_in
,
double
v_in
,
double
&
u
,
double
&
v
,
int
&
iu0
,
int
&
iv0
)
const
{
u
=
fmod1
(
u_in
*
psx
)
*
nu
,
iu0
=
int
(
u
-
supp
*
0.5
+
1
+
nu
)
-
nu
;
...
...
@@ -759,7 +763,7 @@ template<typename T, typename T2=complex<T>> class Helper
vector
<
T2
>
rbuf
,
wbuf
;
bool
do_w_gridding
;
T
w0
,
xdw
;
double
w0
,
xdw
;
size_t
nexp
;
size_t
nvecs
;
vector
<
Lock
>
&
locks
;
...
...
@@ -809,9 +813,9 @@ template<typename T, typename T2=complex<T>> class Helper
T
kernel
[
64
]
ALIGNED
(
64
);
Helper
(
const
GridderConfig
&
gconf_
,
const
T2
*
grid_r_
,
T2
*
grid_w_
,
vector
<
Lock
>
&
locks_
,
T
w0_
=-
1
,
T
dw_
=-
1
)
vector
<
Lock
>
&
locks_
,
double
w0_
=-
1
,
double
dw_
=-
1
)
:
gconf
(
gconf_
),
nu
(
gconf
.
Nu
()),
nv
(
gconf
.
Nv
()),
nsafe
(
gconf
.
Nsafe
()),
supp
(
gconf
.
Supp
()),
beta
(
gconf
.
Beta
()),
grid_r
(
grid_r_
),
supp
(
gconf
.
Supp
()),
beta
(
T
(
gconf
.
Beta
())
)
,
grid_r
(
grid_r_
),
grid_w
(
grid_w_
),
su
(
2
*
nsafe
+
(
1
<<
logsquare
)),
sv
(
2
*
nsafe
+
(
1
<<
logsquare
)),
bu0
(
-
1000000
),
bv0
(
-
1000000
),
rbuf
(
su
*
sv
*
(
grid_r
!=
nullptr
),
T
(
0
)),
...
...
@@ -829,18 +833,18 @@ template<typename T, typename T2=complex<T>> class Helper
T
Wfac
()
const
{
return
kernel
[
2
*
supp
];
}
void
prep
(
const
UVW
&
in
)
{
T
u
,
v
;
gconf
.
getpix
<
T
>
(
in
.
u
,
in
.
v
,
u
,
v
,
iu0
,
iv0
);
T
xsupp
=
T
(
2
)
/
supp
;
auto
x0
=
xsupp
*
(
iu0
-
u
);
auto
y0
=
xsupp
*
(
iv0
-
v
);
double
u
,
v
;
gconf
.
getpix
(
in
.
u
,
in
.
v
,
u
,
v
,
iu0
,
iv0
);
double
xsupp
=
2.
/
supp
;
double
x0
=
xsupp
*
(
iu0
-
u
);
double
y0
=
xsupp
*
(
iv0
-
v
);
for
(
int
i
=
0
;
i
<
supp
;
++
i
)
{
kernel
[
i
]
=
x0
+
i
*
xsupp
;
kernel
[
i
+
supp
]
=
y0
+
i
*
xsupp
;
kernel
[
i
]
=
T
(
x0
+
i
*
xsupp
)
;
kernel
[
i
+
supp
]
=
T
(
y0
+
i
*
xsupp
)
;
}
if
(
do_w_gridding
)
kernel
[
2
*
supp
]
=
min
(
T
(
1
),
xdw
*
xsupp
*
abs
(
w0
-
T
(
in
.
w
)));
kernel
[
2
*
supp
]
=
min
(
T
(
1
),
T
(
xdw
*
xsupp
*
abs
(
w0
-
in
.
w
)));
for
(
size_t
i
=
nexp
;
i
<
nvecs
;
++
i
)
kernel
[
i
]
=
0
;
for
(
size_t
i
=
0
;
i
<
nvecs
;
++
i
)
...
...
@@ -857,6 +861,28 @@ template<typename T, typename T2=complex<T>> class Helper
}
};
template
<
class
T
,
class
Serv
>
class
SubServ
{
private:
const
Serv
&
srv
;
const_mav
<
uint32_t
,
1
>
subidx
;
public:
SubServ
(
const
Serv
&
orig
,
const
const_mav
<
uint32_t
,
1
>
&
subidx_
)
:
srv
(
orig
),
subidx
(
subidx_
){}
size_t
Nvis
()
const
{
return
subidx
.
size
();
}
const
Baselines
&
getBaselines
()
const
{
return
srv
.
getBaselines
();
}
UVW
getCoord
(
size_t
i
)
const
{
return
srv
.
getCoord
(
subidx
[
i
]);
}
complex
<
T
>
getVis
(
size_t
i
)
const
{
return
srv
.
getVis
(
subidx
[
i
]);
}
uint32_t
getIdx
(
size_t
i
)
const
{
return
srv
.
getIdx
(
subidx
[
i
]);
}
void
setVis
(
size_t
i
,
const
complex
<
T
>
&
v
)
const
{
srv
.
setVis
(
subidx
[
i
],
v
);
}
void
addVis
(
size_t
i
,
const
complex
<
T
>
&
v
)
const
{
srv
.
addVis
(
subidx
[
i
],
v
);
}
};
template
<
class
T
,
class
T2
>
class
VisServ
{
private:
...
...
@@ -876,9 +902,8 @@ template<class T, class T2> class VisServ
checkShape
(
idx
.
shape
(),
{
nvis
});
if
(
have_wgt
)
checkShape
(
wgt
.
shape
(),
{
nvis
});
}
VisServ
(
const
VisServ
&
orig
,
const
const_mav
<
uint32_t
,
1
>
&
/*newidx*/
)
:
baselines
(
orig
.
baselines
),
idx
(
orig
.
idx
),
vis
(
orig
.
vis
),
wgt
(
orig
.
wgt
)
{
myfail
(
"must not happen"
);
}
SubServ
<
T
,
VisServ
>
getSubserv
(
const
const_mav
<
uint32_t
,
1
>
&
subidx
)
const
{
return
SubServ
<
T
,
VisServ
>
(
*
this
,
subidx
);
}
size_t
Nvis
()
const
{
return
nvis
;
}
const
Baselines
&
getBaselines
()
const
{
return
baselines
;
}
UVW
getCoord
(
size_t
i
)
const
...
...
@@ -890,7 +915,6 @@ template<class T, class T2> class VisServ
{
vis
(
i
)
=
have_wgt
?
v
*
wgt
(
i
)
:
v
;
}
void
addVis
(
size_t
i
,
const
complex
<
T
>
&
v
)
const
{
vis
(
i
)
+=
have_wgt
?
v
*
wgt
(
i
)
:
v
;
}
bool
isMsServ
()
const
{
return
false
;
}
};
template
<
class
T
,
class
T2
>
VisServ
<
T
,
T2
>
makeVisServ
(
const
Baselines
&
baselines
,
...
...
@@ -916,8 +940,8 @@ template<class T, class T2> class MsServ
checkShape
(
ms
.
shape
(),
{
baselines
.
Nrows
(),
baselines
.
Nchannels
()});
if
(
have_wgt
)
checkShape
(
wgt
.
shape
(),
ms
.
shape
());
}
Ms
Serv
(
const
MsServ
&
orig
,
const
const_mav
<
uint32_t
,
1
>
&
new
idx
)
:
MsServ
(
orig
.
baselines
,
newidx
,
orig
.
ms
,
orig
.
wgt
)
{
}
Sub
Serv
<
T
,
MsServ
>
getSubserv
(
const
const_mav
<
uint32_t
,
1
>
&
sub
idx
)
const
{
return
SubServ
<
T
,
MsServ
>
(
*
this
,
subidx
);
}
size_t
Nvis
()
const
{
return
nvis
;
}
const
Baselines
&
getBaselines
()
const
{
return
baselines
;
}
UVW
getCoord
(
size_t
i
)
const
...
...
@@ -939,7 +963,6 @@ template<class T, class T2> class MsServ
auto
rc
=
baselines
.
getRowChan
(
idx
(
i
));
ms
(
rc
.
row
,
rc
.
chan
)
+=
have_wgt
?
v
*
wgt
(
rc
.
row
,
rc
.
chan
)
:
v
;
}
bool
isMsServ
()
const
{
return
true
;
}
};
template
<
class
T
,
class
T2
>
MsServ
<
T
,
T2
>
makeMsServ
(
const
Baselines
&
baselines
,
...
...
@@ -1215,12 +1238,12 @@ template<typename T> void apply_wcorr(const GridderConfig &gconf,
{
double
fy
=
y0
+
j
*
psy
;
fy
*=
fy
;
double
fct
=
0
;
T
fct
=
0
;
double
tmp
=
1.
-
fx
-
fy
;
if
(
tmp
>=
0
)
{
auto
nm1
=
(
-
fx
-
fy
)
/
(
sqrt
(
1.
-
fx
-
fy
)
+
1.
);
// accurate form of sqrt(1-x-y)
fct
=
(
nm1
<=-
1
)
?
0.
:
kernel
.
corfac
(
nm1
*
dw
);
fct
=
T
(
(
nm1
<=-
1
)
?
0.
:
kernel
.
corfac
(
nm1
*
dw
)
)
;
}
size_t
i2
=
nx_dirty
-
i
,
j2
=
ny_dirty
-
j
;
dirty
(
i
,
j
)
*=
fct
;
...
...
@@ -1315,9 +1338,7 @@ template<typename T, typename Serv> void x2dirty(
wstack_common
(
gconf
,
srv
,
wmin
,
dw
,
nplanes
,
nvis_plane
,
minplane
,
verbosity
);
dirty
.
fill
(
0
);
vector
<
complex
<
T
>>
vis_loc_
;
vector
<
uint32_t
>
idx_loc_
;
vector
<
uint32_t
>
mapper
;
vector
<
uint32_t
>
subidx
;
tmpStorage
<
complex
<
T
>
,
2
>
grid_
({
gconf
.
Nu
(),
gconf
.
Nv
()});
auto
grid
=
grid_
.
getMav
();
tmpStorage
<
complex
<
T
>
,
2
>
tdirty_
(
dirty
.
shape
());
...
...
@@ -1331,38 +1352,15 @@ template<typename T, typename Serv> void x2dirty(
double
wcur
=
wmin
+
iw
*
dw
;
size_t
cnt
=
0
;
mapper
.
resize
(
nvis_plane
[
iw
]);
subidx
.
resize
(
nvis_plane
[
iw
]);
const
auto
&
bla
(
minplane
[
iw
/
supp
]);
for
(
size_t
i
=
0
;
i
<
bla
.
size
();
++
i
)
if
((
int
(
iw
)
>=
bla
[
i
].
minplane
)
&&
(
int
(
iw
)
<
bla
[
i
].
minplane
+
int
(
supp
)))
mapper
[
cnt
++
]
=
bla
[
i
].
idx
;
idx_loc_
.
resize
(
nvis_plane
[
iw
]);
if
(
srv
.
isMsServ
())
{
#pragma omp parallel for num_threads(nthreads)
for
(
size_t
i
=
0
;
i
<
nvis_plane
[
iw
];
++
i
)
idx_loc_
[
i
]
=
srv
.
getIdx
(
mapper
[
i
]);
grid
.
fill
(
0
);
auto
idx_loc
=
const_mav
<
uint32_t
,
1
>
(
idx_loc_
.
data
(),
{
idx_loc_
.
size
()});
Serv
newsrv
(
srv
,
idx_loc
);
x2grid_c
(
gconf
,
newsrv
,
grid
,
wcur
,
dw
);
}
else
{
vis_loc_
.
resize
(
nvis_plane
[
iw
]);
#pragma omp parallel for num_threads(nthreads)
for
(
size_t
i
=
0
;
i
<
nvis_plane
[
iw
];
++
i
)
{
auto
ipart
=
mapper
[
i
];
vis_loc_
[
i
]
=
srv
.
getVis
(
ipart
);
idx_loc_
[
i
]
=
srv
.
getIdx
(
ipart
);
}
grid
.
fill
(
0
);
auto
vis_loc
=
const_mav
<
complex
<
T
>
,
1
>
(
vis_loc_
.
data
(),
{
nvis_plane
[
iw
]});
auto
idx_loc
=
const_mav
<
uint32_t
,
1
>
(
idx_loc_
.
data
(),
{
nvis_plane
[
iw
]});
vis2grid_c
(
srv
.
getBaselines
(),
gconf
,
idx_loc
,
vis_loc
,
grid
,
nullmav
<
T
,
1
>
(),
wcur
,
dw
);
}
subidx
[
cnt
++
]
=
bla
[
i
].
idx
;
auto
subidx2
=
const_mav
<
uint32_t
,
1
>
(
subidx
.
data
(),
{
subidx
.
size
()});
auto
subsrv
=
srv
.
getSubserv
(
subidx2
);
grid
.
fill
(
0
);
x2grid_c
(
gconf
,
subsrv
,
grid
,
wcur
,
dw
);
gconf
.
grid2dirty_c
(
cmav
(
grid
),
tdirty
);
gconf
.
apply_wscreen
(
cmav
(
tdirty
),
tdirty
,
wcur
,
true
);
#pragma omp parallel for num_threads(nthreads)
...
...
@@ -1424,9 +1422,7 @@ template<typename T, typename Serv> void dirty2x(
// correct for w gridding
apply_wcorr
(
gconf
,
tdirty
,
ES_Kernel_with_correction
(
supp
,
nthreads
),
dw
);
vector
<
complex
<
T
>>
vis_loc_
;
vector
<
uint32_t
>
idx_loc_
;
vector
<
uint32_t
>
mapper
;
vector
<
uint32_t
>
subidx
;
tmpStorage
<
complex
<
T
>
,
2
>
grid_
({
gconf
.
Nu
(),
gconf
.
Nv
()});
auto
grid
=
grid_
.
getMav
();
tmpStorage
<
complex
<
T
>
,
2
>
tdirty2_
({
nx_dirty
,
ny_dirty
});
...
...
@@ -1446,37 +1442,15 @@ template<typename T, typename Serv> void dirty2x(
gconf
.
apply_wscreen
(
cmav
(
tdirty2
),
tdirty2
,
wcur
,
false
);
gconf
.
dirty2grid_c
(
cmav
(
tdirty2
),
grid
);
subidx
.
resize
(
nvis_plane
[
iw
]);
size_t
cnt
=
0
;
mapper
.
resize
(
nvis_plane
[
iw
]);
const
auto
&
bla
(
minplane
[
iw
/
supp
]);
for
(
size_t
i
=
0
;
i
<
bla
.
size
();
++
i
)
if
((
int
(
iw
)
>=
bla
[
i
].
minplane
)
&&
(
int
(
iw
)
<
bla
[
i
].
minplane
+
int
(
supp
)))
mapper
[
cnt
++
]
=
bla
[
i
].
idx
;
idx_loc_
.
resize
(
nvis_plane
[
iw
]);
if
(
srv
.
isMsServ
())
{
#pragma omp parallel for num_threads(nthreads)
for
(
size_t
i
=
0
;
i
<
nvis_plane
[
iw
];
++
i
)
idx_loc_
[
i
]
=
srv
.
getIdx
(
mapper
[
i
]);
auto
idx_loc
=
const_mav
<
uint32_t
,
1
>
(
idx_loc_
.
data
(),
{
idx_loc_
.
size
()});
Serv
newsrv
(
srv
,
idx_loc
);
grid2x_c
(
gconf
,
cmav
(
grid
),
newsrv
,
wcur
,
dw
);
}
else
{
vis_loc_
.
resize
(
nvis_plane
[
iw
]);
auto
vis_loc
=
mav
<
complex
<
T
>
,
1
>
(
vis_loc_
.
data
(),
{
nvis_plane
[
iw
]});
vis_loc
.
fill
(
0
);
auto
idx_loc
=
mav
<
uint32_t
,
1
>
(
idx_loc_
.
data
(),
{
nvis_plane
[
iw
]});
#pragma omp parallel for num_threads(nthreads)
for
(
size_t
i
=
0
;
i
<
nvis_plane
[
iw
];
++
i
)
idx_loc
[
i
]
=
srv
.
getIdx
(
mapper
[
i
]);
grid2vis_c
(
srv
.
getBaselines
(),
gconf
,
cmav
(
idx_loc
),
cmav
(
grid
),
vis_loc
,
nullmav
<
T
,
1
>
(),
wcur
,
dw
);
#pragma omp parallel for num_threads(nthreads)
for
(
size_t
i
=
0
;
i
<
nvis_plane
[
iw
];
++
i
)
srv
.
addVis
(
mapper
[
i
],
vis_loc
[
i
]);
}
subidx
[
cnt
++
]
=
bla
[
i
].
idx
;
auto
subidx2
=
const_mav
<
uint32_t
,
1
>
(
subidx
.
data
(),
{
subidx
.
size
()});
auto
subsrv
=
srv
.
getSubserv
(
subidx2
);
grid2x_c
(
gconf
,
cmav
(
grid
),
subsrv
,
wcur
,
dw
);
}
}
else
...
...
nifty_gridder.cc
View file @
ce4b57cf
...
...
@@ -138,9 +138,9 @@ Class storing UVW coordinates and channel information.
Parameters
==========
coord: np.array((nrows, 3), dtype=np.float)
coord: np.array((nrows, 3), dtype=np.float
64
)
u, v and w coordinates for each row
freq: np.array((nchannels,), dtype=np.float)
freq: np.array((nchannels,), dtype=np.float
64
)
frequency for each individual channel (in Hz)
)"""
;
class
PyBaselines
:
public
Baselines
...
...
@@ -305,6 +305,8 @@ pixsize_x: float
Pixel size in x direction (radians)
pixsize_y: float
Pixel size in y direction (radians)
nthreads: int
the number of threads to use for all calculations involving this object.
)"""
;
class
PyGridderConfig
:
public
GridderConfig
{
...
...
@@ -714,6 +716,35 @@ template<typename T> pyarr<T> vis2dirty2(const PyBaselines &baselines,
}
return
dirty
;
}
constexpr
auto
vis2dirty_DS
=
R"""(
Converts an array of visibilities to a dirty image.
Parameters
==========
baselines: Baselines
the Baselines object
gconf: GridderConf
the GridderConf object to be used
(used to optimize the ordering of the indices)
idx: np.array((nvis,), dtype=np.uint32)
the indices for the provided visibilities
vis: np.array(nvis,), dtype=np.complex64 or np.complex128)
The input visibilities
Its data type determines the precision in which the calculation is carried
out.
wgt: np.array((nvis,), dtype=float with same precision as `vis`, optional
If present, visibilities are multiplied by the corresponding entries.
do_wstacking: bool
if True, the full improved w-stacking algorithm is carried out, otherwise
the w values are assumed to be zero.
Returns
=======
np.array((nxdirty, nydirty), dtype=float of same precision as `vis`.)
The dirty image
)"""
;
py
::
array
Pyvis2dirty
(
const
PyBaselines
&
baselines
,
const
PyGridderConfig
&
gconf
,
const
py
::
array
&
idx
,
const
py
::
array
&
vis
,
const
py
::
object
&
wgt
,
bool
do_wstacking
)
...
...
@@ -745,6 +776,34 @@ template<typename T> pyarr<complex<T>> dirty2vis2(const PyBaselines &baselines,
}
return
vis
;
}
constexpr
auto
dirty2vis_DS
=
R"""(
Converts a dirty image into a 1D array of visibilities.
Parameters
==========
baselines: Baselines
the Baselines object
gconf: GridderConf
the GridderConf object to be used
(used to optimize the ordering of the indices)
idx: np.array((nvis,), dtype=np.uint32)
the indices for the visibilities to be computed
dirty: np.array((nxdirty, nydirty), dtype=np.float32 or np.float64)
dirty image
Its data type determines the precision in which the calculation is carried
out.
wgt: np.array((nvis,), same dtype as `dirty`, optional
If present, visibilities are multiplied by the corresponding entries.
do_wstacking: bool
if True, the full improved w-stacking algorithm is carried out, otherwise
the w values are assumed to be zero.
Returns
=======
np.array((nvis,), dtype=complex of same precision as `dirty`.)
The visibility data
)"""
;
py
::
array
Pydirty2vis
(
const
PyBaselines
&
baselines
,
const
PyGridderConfig
&
gconf
,
const
py
::
array
&
idx
,
const
py
::
array
&
dirty
,
const
py
::
object
&
wgt
,
bool
do_wstacking
)
...
...
@@ -779,6 +838,43 @@ template<typename T> py::array ms2dirty2(const py::array &uvw_,
return
dirty
;
}
constexpr
auto
ms2dirty_DS
=
R"""(
Converts an MS object to dirty image.
Parameters
==========
uvw: np.array((nrows, 3), dtype=np.float64)
UVW coordinates from the measurement set
freq: np.array((nchan,), dtype=np.float64)
channel frequencies
ms: np.array((nrows, nchan,), dtype=np.complex64 or np.complex128)
the input measurement set data.
Its data type determines the precision in which the calculation is carried
out.
wgt: np.array((nrows, nchan), float with same precision as `ms`), optional
If present, its values are multiplied to the output
npix_x, npix_y: int
dimensions of the dirty image
pixsize_x, pixsize_y: float
angular pixel size (in radians) of the dirty image
epsilon: float
accuracy at which the computation should be done. Must be larger than 2e-13.
If `ms` has type np.complex64, it must be larger than 1e-5.
do_wstacking: bool
if True, the full improved w-stacking algorithm is carried out, otherwise
the w values are assumed to be zero.
nthreads: int
number of threads to use for the calculation
verbosity: int
0: no output
1: some output
2: detailed output
Returns
=======
np.array((nxdirty, nydirty), dtype=float of same precision as `ms`)
the dirty image
)"""
;
py
::
array
Pyms2dirty
(
const
py
::
array
&
uvw
,
const
py
::
array
&
freq
,
const
py
::
array
&
ms
,
const
py
::
object
&
wgt
,
size_t
npix_x
,
size_t
npix_y
,
double
pixsize_x
,
double
pixsize_y
,
double
epsilon
,
...
...
@@ -816,6 +912,41 @@ template<typename T> py::array dirty2ms2(const py::array &uvw_,
return
ms
;
}
constexpr
auto
dirty2ms_DS
=
R"""(
Converts a dirty image to an MS object.
Parameters
==========
uvw: np.array((nrows, 3), dtype=np.float64)
UVW coordinates from the measurement set
freq: np.array((nchan,), dtype=np.float64)
channel frequencies
dirty: np.array((nxdirty, nydirty), dtype=np.float32 or np.float64)
dirty image
Its data type determines the precision in which the calculation is carried
out.
wgt: np.array((nrows, nchan), same dtype as `dirty`), optional
If present, its values are multiplied to the output
pixsize_x, pixsize_y: float
angular pixel size (in radians) of the dirty image
epsilon: float
accuracy at which the computation should be done. Must be larger than 2e-13.
If `dirty` has type np.float32, it must be larger than 1e-5.
do_wstacking: bool
if True, the full improved w-stacking algorithm is carried out, otherwise
the w values are assumed to be zero.
nthreads: int
number of threads to use for the calculation
verbosity: int
0: no output
1: some output
2: detailed output
Returns
=======
np.array((nrows, nchan,), dtype=complex of same precision as `dirty`)
the measurement set data.
)"""
;
py
::
array
Pydirty2ms
(
const
py
::
array
&
uvw
,
const
py
::
array
&
freq
,
const
py
::
array
&
dirty
,
const
py
::
object
&
wgt
,
double
pixsize_x
,
double
pixsize_y
,
double
epsilon
,
...
...
@@ -909,15 +1040,15 @@ PYBIND11_MODULE(nifty_gridder, m)
"grid"
_a
,
"wgt"
_a
=
None
);
m
.
def
(
"get_correlations"
,
&
Pyget_correlations
<
double
>
,
"baselines"
_a
,
"gconf"
_a
,
"idx"
_a
,
"du"
_a
,
"dv"
_a
,
"wgt"
_a
=
None
);
m
.
def
(
"vis2dirty"
,
&
Pyvis2dirty
,
"baselines"
_a
,
"gconf"
_a
,
m
.
def
(
"vis2dirty"
,
&
Pyvis2dirty
,
vis2dirty_DS
,
"baselines"
_a
,
"gconf"
_a
,
"idx"
_a
,
"vis"
_a
,
"wgt"
_a
=
None
,
"do_wstacking"
_a
=
false
);
m
.
def
(
"dirty2vis"
,
&
Pydirty2vis
,
"baselines"
_a
,
"gconf"
_a
,
m
.
def
(
"dirty2vis"
,
&
Pydirty2vis
,
"baselines"
_a
,
dirty2vis_DS
,
"gconf"
_a
,
"idx"
_a
,
"dirty"
_a
,
"wgt"
_a
=
None
,
"do_wstacking"
_a
=
false
);
m
.
def
(
"ms2dirty"
,
&
Pyms2dirty
,
"uvw"
_a
,
"freq"
_a
,
"ms"
_a
,
"wgt"
_a
=
None
,
"npix_x"
_a
,
"npix_y"
_a
,
"pixsize_x"
_a
,
"pixsize_y"
_a
,
"epsilon"
_a
,
m
.
def
(
"ms2dirty"
,
&
Pyms2dirty
,
ms2dirty_DS
,
"uvw"
_a
,
"freq"
_a
,
"ms"
_a
,
"wgt"
_a
=
None
,
"npix_x"
_a
,
"npix_y"
_a
,
"pixsize_x"
_a
,
"pixsize_y"
_a
,
"epsilon"
_a
,
"do_wstacking"
_a
=
false
,
"nthreads"
_a
=
1
,
"verbosity"
_a
=
0
);
m
.
def
(
"dirty2ms"
,
&
Pydirty2ms
,
dirty2ms_DS
,
"uvw"
_a
,
"freq"
_a
,
"dirty"
_a
,
"wgt"
_a
=
None
,
"pixsize_x"
_a
,
"pixsize_y"
_a
,
"epsilon"
_a
,
"do_wstacking"
_a
=
false
,
"nthreads"
_a
=
1
,
"verbosity"
_a
=
0
);
m
.
def
(
"dirty2ms"
,
&
Pydirty2ms
,
"uvw"
_a
,
"freq"
_a
,
"dirty"
_a
,
"wgt"
_a
=
None
,
"pixsize_x"
_a
,
"pixsize_y"
_a
,
"epsilon"
_a
,
"do_wstacking"
_a
=
false
,
"nthreads"
_a
=
1
,
"verbosity"
_a
=
0
);
}
test.py
View file @
ce4b57cf
...
...
@@ -7,7 +7,6 @@ from numpy.testing import assert_, assert_allclose, assert_array_almost_equal
pmp
=
pytest
.
mark
.
parametrize
def
_init_gridder
(
nxdirty
,
nydirty
,
epsilon
,
nchan
,
nrow
):
pixsize
=
np
.
pi
/
180
/
60
/
nxdirty
conf
=
ng
.
GridderConfig
(
nxdirty
=
nxdirty
,
...
...
@@ -45,13 +44,103 @@ def _dft(uvw, vis, conf, apply_w):
def
_l2error
(
a
,
b
):
return
np
.
sqrt
(
np
.
sum
(
np
.
abs
(
a
-
b
)
**
2
)
/
np
.
sum
(
np
.
abs
(
a
)
**
2
))
return
np
.
sqrt
(
np
.
sum
(
np
.
abs
(
a
-
b
)
**
2
)
/
np
.
maximum
(
np
.
sum
(
np
.
abs
(
a
)
**
2
),
np
.
sum
(
np
.
abs
(
b
)
**
2
)))
def
explicit_gridder
(
uvw
,
freq
,
ms
,
wgt
,
nxdirty
,
nydirty
,
xpixsize
,
ypixsize
,
apply_w
):
speedoflight
=
299792458.
x
,
y
=
np
.
meshgrid
(
*
[
-
ss
/
2
+
np
.
arange
(
ss
)
for
ss
in
[
nxdirty
,
nydirty
]],
indexing
=
'ij'
)
x
*=
xpixsize
y
*=
ypixsize
res
=
np
.
zeros
((
nxdirty
,
nydirty
))
eps
=
x
**
2
+
y
**
2
if
apply_w
:
nm1
=
-
eps
/
(
np
.
sqrt
(
1.
-
eps
)
+
1.
)
n
=
nm1
+
1
else
:
nm1
=
0.
n
=
1.
for
row
in
range
(
ms
.
shape
[
0
]):
for
chan
in
range
(
ms
.
shape
[
1
]):
phase
=
(
freq
[
chan
]
/
speedoflight
*
(
x
*
uvw
[
row
,
0
]
+
y
*
uvw
[
row
,
1
]
-
uvw
[
row
,
2
]
*
nm1
))
if
wgt
is
None
:
res
+=
(
ms
[
row
,
chan
]
*
np
.
exp
(
2j
*
np
.
pi
*
phase
)).
real
else
:
res
+=
(
ms
[
row
,
chan
]
*
wgt
[
row
,
chan
]
*
np
.
exp
(
2j
*
np
.
pi
*
phase
)).
real
return
res
/
n
@
pmp
(
"nxdirty"
,
(
30
,
128
))
@
pmp
(
"nydirty"
,
(
128
,
250
))
@
pmp
(
"nrow"
,
(
2
,
27
))
@
pmp
(
"nchan"
,
(
1
,
5
))
@
pmp
(
"epsilon"
,
(
1e-3
,
1e-5
,
1e-7
,
5e-13
))
@
pmp
(
"singleprec"
,
(
True
,
False
))
@
pmp
(
"wstacking"
,
(
True
,
False
))
@
pmp
(
"use_wgt"
,
(
True
,
False
))
@
pmp
(
"nthreads"
,
(
1
,
2
))
def
test_adjointness_ms2dirty
(
nxdirty
,
nydirty
,
nrow
,
nchan
,
epsilon
,
singleprec
,
wstacking
,
use_wgt
,
nthreads
):
if
singleprec
and
epsilon
<
5e-6
:
return
np
.
random
.
seed
(
42
)
pixsizex
=
np
.
pi
/
180
/
60
/
nxdirty
*
0.2398
pixsizey
=
np
.
pi
/
180
/
60
/
nxdirty
speedoflight
,
f0
=
3e8
,
1e9
freq
=
f0
+
np
.
arange
(
nchan
)
*
(
f0
/
nchan
)
uvw
=
(
np
.
random
.
rand
(
nrow
,
3
)
-
0.5
)
/
(
pixsizey
*
f0
/
speedoflight
)
ms
=
np
.
random
.
rand
(
nrow
,
nchan
)
-
0.5
+
1j
*
(
np
.
random
.
rand
(
nrow
,
nchan
)
-
0.5
)
wgt
=
np
.
random
.
rand
(
nrow
,
nchan
)
if
use_wgt
else
None
dirty
=
np
.
random
.
rand
(
nxdirty
,
nydirty
)
-
0.5
if
singleprec
:
ms
=
ms
.
astype
(
"c8"
)
dirty
=
dirty
.
astype
(
"f4"
)
if
wgt
is
not
None
:
wgt
=
wgt
.
astype
(
"f4"
)
dirty2
=
ng
.
ms2dirty
(
uvw
,
freq
,
ms
,
wgt
,
nxdirty
,
nydirty
,
pixsizex
,
pixsizey
,
epsilon
,
wstacking
,
nthreads
,
2
).
astype
(
"f8"
)
ms2
=
ng
.
dirty2ms
(
uvw
,
freq
,
dirty
,
wgt
,
pixsizex
,
pixsizey
,
epsilon
,
wstacking
,
nthreads
,
0
).
astype
(
"c16"
)
tol
=
5e-5
if
singleprec
else
5e-13
assert_allclose
(
np
.
vdot
(
ms
,
ms2
).
real
,
np
.
vdot
(
dirty2
,
dirty
),
rtol
=
tol
)
@
pmp
(
'nxdirty'
,
[
16
,
64
])
@
pmp
(
'nydirty'
,
[
64
])
@
pmp
(
"nrow"
,
(
2
,
27
))
@
pmp
(
"nchan"
,
(
1
,
5
))
@
pmp
(
"epsilon"
,
(
1e-2
,
1e-3
,
5e-5
,
1e-7
,
5e-13
))
@
pmp
(
"singleprec"
,
(
True
,
False
))
@
pmp
(
"wstacking"
,
(
True
,
False
))
@
pmp
(
"use_wgt"
,
(
False
,
True
))
@
pmp
(
"nthreads"
,
(
1
,
2
))
@
pmp
(
"fov"
,
(
1.
,
20.
))
def
test_ms2dirty_against_wdft
(
nxdirty
,
nydirty
,
nrow
,
nchan
,
epsilon
,
singleprec
,
wstacking
,
use_wgt
,
fov
,
nthreads
):
if
singleprec
and
epsilon
<
5e-5
:
return
np
.
random
.
seed
(
40
)
pixsizex
=
fov
*
np
.
pi
/
180
/
nxdirty
pixsizey
=
fov
*
np
.
pi
/
180
/
nydirty
*
1.1
speedoflight
,
f0
=
3e8
,
1e9
freq
=
f0
+
np
.
arange
(
nchan
)
*
(
f0
/
nchan
)
uvw
=
(
np
.
random
.
rand
(
nrow
,
3
)
-
0.5
)
/
(
pixsizex
*
f0
/
speedoflight
)
ms
=
np
.
random
.
rand
(
nrow
,
nchan
)
-
0.5
+
1j
*
(
np
.
random
.
rand
(
nrow
,
nchan
)
-
0.5
)
wgt
=
np
.
random
.
rand
(
nrow
,
nchan
)
if
use_wgt
else
None
if
singleprec
:
ms
=
ms
.
astype
(
"c8"
)
if
wgt
is
not
None
:
wgt
=
wgt
.
astype
(
"f4"
)
dirty
=
ng
.
ms2dirty
(
uvw
,
freq
,
ms
,
wgt
,
nxdirty
,
nydirty
,
pixsizex
,
pixsizey
,
epsilon
,
wstacking
,
nthreads
,
0
).
astype
(
"f8"
)
ref
=
explicit_gridder
(
uvw
,
freq
,
ms
,
wgt
,
nxdirty
,
nydirty
,
pixsizex
,
pixsizey
,
wstacking
)
assert_allclose
(
_l2error
(
dirty
,
ref
),
0
,
atol
=
epsilon
)
@
pmp
(
"nxdirty"
,
(
128
,
300
))
@
pmp
(
"nydirty"
,
(
128
,
250
))
@
pmp
(
"nrow"
,
(
1
,
10
,
1000
0
))
@
pmp
(
"nchan"
,
(
1
,
10
,
100
))
@
pmp
(
"nrow"
,
(
1
,
100
))
@
pmp
(
"nchan"
,
(
1
,
10
))
@
pmp
(
"epsilon"
,
(
1e-2
,
1e-7
,
2e-13
))
def
test_adjointness
(
nxdirty
,
nydirty
,
nrow
,
nchan
,
epsilon
):
np
.
random
.
seed
(
42
)
...
...
@@ -68,8 +157,8 @@ def test_adjointness(nxdirty, nydirty, nrow, nchan, epsilon):
@
pmp
(
"nxdirty"
,
(
128
,
300
))
@
pmp
(
"nydirty"
,
(
128
,
250
))
@
pmp
(
"nrow"
,
(
1
,
1
0
,
10000
))
@
pmp
(
"nchan"
,
(
1
,
1
0
,
100
))
@
pmp
(
"nrow"
,
(
1
,
1
27
))
@
pmp
(
"nchan"
,
(
1
,
1
7
))
@
pmp
(
"epsilon"
,
(
1e-2
,
1e-7
,
2e-13
))
def
test_adjointness_wgridding
(
nxdirty
,
nydirty
,
nrow
,
nchan
,
epsilon
):
np
.
random
.
seed
(
42
)
...
...
@@ -82,40 +171,10 @@ def test_adjointness_wgridding(nxdirty, nydirty, nrow, nchan, epsilon):
rtol
=
2e-13
)
@
pmp
(
"nxdirty"
,
(
128
,
300
))
@
pmp
(
"nydirty"
,
(
128
,
250
))
@
pmp
(
"nrow"
,
(
1
,
10
,
10000
))
@
pmp
(
"nchan"
,
(
1
,
10
,
100
))
@
pmp
(
"epsilon"
,
(
1e-2
,
1e-3
,
5e-5
,
1e-6
,
1e-7
,
5e-13
))
@
pmp
(
"singleprec"
,
(
True
,
False
))
@
pmp
(
"wstacking"
,
(
True
,
False
))
def
test_adjointness_wgridding_highlevel
(
nxdirty
,
nydirty
,
nrow
,
nchan
,
epsilon
,
singleprec
,
wstacking
):
if
singleprec
and
epsilon
<
5e-6
:
return
np
.
random
.
seed
(
42
)