File: pyfunctions.cpp

package info (click to toggle)
aoflagger 3.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 4,476 kB
  • sloc: cpp: 51,868; python: 152; sh: 25; makefile: 17
file content (206 lines) | stat: -rw-r--r-- 8,334 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include "pyfunctions.h"

#include <pybind11/pybind11.h>

#include <stdexcept>

namespace py = pybind11;

namespace aoflagger_python
{

static py::object flagFunction;

py::object get_flag_function()
{
	return flagFunction;
}

void set_flag_function(PyObject* callable)
{
	flagFunction = py::reinterpret_borrow<py::object>(py::handle(callable));
}

py::list polarizations(const aoflagger_lua::Data* data)
{
	const std::vector<aocommon::PolarizationEnum> pols = data->TFData().Polarizations();
	py::list polList;
	for (aocommon::PolarizationEnum p : pols)
		polList.append(p);
	return polList;
}

py::array_t<double> GetImageBuffer(const aoflagger::ImageSet* imageSet, size_t imageIndex)
{
	if(imageIndex >= imageSet->ImageCount())
		throw std::out_of_range("aoflagger.get_image_buffer: Image index out of bounds");
	const float* values = imageSet->ImageBuffer(imageIndex);
	py::buffer_info buf = py::buffer_info(
		nullptr, // ask NumPy to allocate
		sizeof(double),
		py::format_descriptor<double>::value,
		2,
		{ptrdiff_t(imageSet->Height()), ptrdiff_t(imageSet->Width())},
		{ sizeof(double)*imageSet->Width(), sizeof(double) }  /* Strides for each dimension */
	);
	py::array_t<double> result(buf);

	buf = result.request();
	char *resultData = (char*) buf.ptr;
	int stride0 = buf.strides[0];
	int stride1 = buf.strides[1];
	for(size_t y=0; y!=imageSet->Height(); ++y)
	{
		const float* rowOut = values + y * imageSet->HorizontalStride();
		char* rowIn = resultData + y * stride0;
		for(size_t x=0; x!=imageSet->Width(); ++x)
		{
			*reinterpret_cast<double*>(rowIn + x * stride1) = rowOut[x];
		}
	}
	return result;
}

void SetImageBuffer(aoflagger::ImageSet* imageSet, size_t imageIndex, py::array_t<double>& values)
{
	if(imageIndex >= imageSet->ImageCount())
		throw std::out_of_range("aoflagger.get_image_buffer: Image index out of bounds");
	if(values.ndim() != 2)
		throw std::runtime_error("ImageSet.set_image_buffer(): require a two-dimensional array");
	if(values.shape(0) != int(imageSet->Height()) || values.shape(1) != int(imageSet->Width()))
		throw std::runtime_error("ImageSet.set_image_buffer(): dimensions of provided array doesn't match with image set");
	const py::buffer_info buf = values.request();
	int stride0 = buf.strides[0];
	int stride1 = buf.strides[1];
	const char *data = static_cast<const char*>( buf.ptr );
	if(!data)
		throw std::runtime_error("Data needs to be provided that is interpretable as a double array");
	float* buffer = imageSet->ImageBuffer(imageIndex);
	for(size_t y=0; y!=imageSet->Height(); ++y)
	{
		const char* rowIn = data + y * stride0;
		float* rowOut = buffer + y * imageSet->HorizontalStride();
		for(size_t x=0; x!=imageSet->Width(); ++x)
		{
			rowOut[x] = *reinterpret_cast<const double*>(rowIn + x*stride1);
		}
	}
}

py::array_t<bool> GetBuffer(const aoflagger::FlagMask* flagMask)
{
	const bool* values = flagMask->Buffer();
	py::buffer_info buf = py::buffer_info(
		nullptr, // ask NumPy to allocate
		sizeof(bool),
		py::format_descriptor<bool>::value,
		2,
		{ptrdiff_t(flagMask->Height()), ptrdiff_t(flagMask->Width())},
		{ sizeof(bool)*flagMask->Width(), sizeof(bool) }  /* Strides for each dimension */
	);
	py::array_t<bool> result(buf);
	buf = result.request();
	char* resultData = static_cast<char*>(buf.ptr);
	int stride0 = buf.strides[0];
	int stride1 = buf.strides[1];
	for(size_t y=0; y!=flagMask->Height(); ++y)
	{
		const bool* rowOut = values + y * flagMask->HorizontalStride();
		char* rowIn = resultData + y * stride0;
		for(size_t x=0; x!=flagMask->Width(); ++x)
		{
			*reinterpret_cast<bool*>(rowIn + x * stride1) = rowOut[x];
		}
	}
	return result;
}

void SetBuffer(aoflagger::FlagMask* flagMask, pybind11::array_t<bool>& values)
{
	if(values.ndim() != 2)
		throw std::runtime_error("FlagMask.set_buffer(): Invalid dimensions specified for data array; two dimensional array required");
	if(values.shape(0) != int(flagMask->Height()) || values.shape(1) != int(flagMask->Width()))
		throw std::runtime_error("FlagMask.set_buffer(): dimensions of provided array don't match with image set");
	py::buffer_info buf = values.request();
	const char *data = static_cast<const char*>(buf.ptr);
	if(!data)
		throw std::runtime_error("Data needs to be provided that is interpretable as a bool array");
	bool* buffer = flagMask->Buffer();
	int stride0 = buf.strides[0];
	int stride1 = buf.strides[1];
	for(size_t y=0; y!=flagMask->Height(); ++y)
	{
		const char* rowIn = data + y * stride0;
		bool* rowOut = buffer + y * flagMask->HorizontalStride();
		for(size_t x=0; x!=flagMask->Width(); ++x)
		{
			rowOut[x] = *reinterpret_cast<const double*>(rowIn + x*stride1);
		}
	}
}

py::object MakeImageSet1(aoflagger::AOFlagger* flagger, size_t width, size_t height, size_t count)
{ return py::cast(flagger->MakeImageSet(width, height, count)); }

py::object MakeImageSet2(aoflagger::AOFlagger* flagger, size_t width, size_t height, size_t count, size_t widthCapacity)
{ return py::cast(flagger->MakeImageSet(width, height, count, widthCapacity)); }

py::object MakeImageSet3(aoflagger::AOFlagger* flagger, size_t width, size_t height, size_t count, float initialValue)
{ return py::cast(flagger->MakeImageSet(width, height, count, initialValue)); }

py::object MakeImageSet4(aoflagger::AOFlagger* flagger, size_t width, size_t height, size_t count, float initialValue, size_t widthCapacity)
{ return py::cast(flagger->MakeImageSet(width, height, count, initialValue, widthCapacity)); }

py::object MakeFlagMask1(aoflagger::AOFlagger* flagger, size_t width, size_t height)
{ return py::cast(flagger->MakeFlagMask(width, height)); }

py::object MakeFlagMask2(aoflagger::AOFlagger* flagger, size_t width, size_t height, bool initialValue)
{ return py::cast(flagger->MakeFlagMask(width, height, initialValue)); }

py::object FindStrategyFile1(aoflagger::AOFlagger* flagger, enum aoflagger::TelescopeId telescopeId)
{ return FindStrategyFile2(flagger, telescopeId, ""); }

py::object FindStrategyFile2(aoflagger::AOFlagger* flagger, enum aoflagger::TelescopeId telescopeId, const char* scenario)
{ 
	std::string path = flagger->FindStrategyFile(telescopeId, std::string(scenario));
	if(path.empty())
		throw std::runtime_error("find_strategy(): Could not find requested strategy");
	return py::cast(path);
}

py::object LoadStrategyFile(aoflagger::AOFlagger* flagger, const char* filename)
{ return py::cast(flagger->LoadStrategyFile(std::string(filename)), py::return_value_policy::move); }

py::object Run1(aoflagger::Strategy* strategy, const aoflagger::ImageSet& input)
{ return py::cast(strategy->Run(input)); }

py::object Run2(aoflagger::Strategy* strategy, const aoflagger::ImageSet& input, const aoflagger::FlagMask& existingFlags)
{ return py::cast(strategy->Run(input, existingFlags)); }

py::object MakeQualityStatistics1(aoflagger::AOFlagger* flagger, py::array_t<double>& scanTimes, py::array_t<double>& channelFrequencies, size_t nPolarizations, bool computeHistograms)
{
	if(scanTimes.ndim() != 1)
		throw std::runtime_error("AOFlagger.make_quality_statistics(): Invalid dimensions specified for scanTimes array; one dimensional array required");
	size_t nScans = scanTimes.shape(0);
	py::buffer_info tbuf = scanTimes.request();
	const double *scanTimesArr = reinterpret_cast<const double*>(tbuf.ptr);
	if(!scanTimesArr)
		throw std::runtime_error("scanTimes data needs to be provided that is interpretable as a double array");
	
	if(channelFrequencies.ndim() != 1)
		throw std::runtime_error("AOFlagger.make_quality_statistics(): Invalid dimensions specified for channelFrequencies array; one dimensional array required");
	size_t nChannels = channelFrequencies.shape(0);
	py::buffer_info fbuf = scanTimes.request();
	const double *channelFrequenciesArr = reinterpret_cast<const double*>(fbuf.ptr);
	if(!channelFrequenciesArr)
		throw std::runtime_error("Data needs to be provided that is interpretable as a double array");
	
	return py::cast(flagger->MakeQualityStatistics(scanTimesArr, nScans, channelFrequenciesArr, nChannels, nPolarizations, computeHistograms));
}

py::object MakeQualityStatistics2(aoflagger::AOFlagger* flagger, py::array_t<double>& scanTimes, py::array_t<double>& channelFrequencies, size_t nPolarizations)
{
	return MakeQualityStatistics1(flagger, scanTimes, channelFrequencies, nPolarizations, false);
}

} // namespace