casacore
Loading...
Searching...
No Matches
AntennaPairFile.h
Go to the documentation of this file.
1#ifndef CASACORE_ANTENNA_PAIR_FILE_H_
2#define CASACORE_ANTENNA_PAIR_FILE_H_
3
5
6#include <cassert>
7#include <limits>
8#include <stdexcept>
9#include <string>
10#include <vector>
11
12namespace casacore {
13
25 public:
26 AntennaPairFile() noexcept = default;
27
29 : file_(std::move(source.file_)),
31 data_(source.data_) {
32 source.rows_in_pattern_ = 0;
33 source.data_.clear();
34 }
35
36 ~AntennaPairFile() noexcept { Close(); }
37
39 Close();
40 file_ = std::move(rhs.file_);
41 rows_in_pattern_ = rhs.rows_in_pattern_;
42 data_ = rhs.data_;
43 rhs.rows_in_pattern_ = 0;
44 rhs.data_.clear();
45 return *this;
46 }
47
51 static AntennaPairFile CreateNew(const std::string& filename) {
52 return AntennaPairFile(filename);
53 }
54
59 static AntennaPairFile OpenExisting(const std::string& filename) {
60 return AntennaPairFile(filename, true);
61 }
62
63 void WriteAntenna1(uint64_t row, int32_t antenna1) { WriteAntenna<0>(row, antenna1); }
64
65 void WriteAntenna2(uint64_t row, int32_t antenna2) { WriteAntenna<1>(row, antenna2); }
66
67 void WritePair(uint64_t row, int32_t antenna1, int32_t antenna2) {
68 WriteAntenna<0>(row, antenna1);
69 WriteAntenna<1>(row, antenna2);
70 }
71
72 int32_t ReadAntenna1(uint64_t row) { return ReadAntenna<0>(row); }
73
74 int32_t ReadAntenna2(uint64_t row) { return ReadAntenna<1>(row); }
75
76 void Close() {
77 if (file_.IsOpen()) {
78 if (rows_in_pattern_ == 0) {
80 WriteData();
81 }
82 file_.Close();
84 data_.clear();
85 }
86 }
87
88 const std::string& Filename() const { return file_.Filename(); }
89
94 uint64_t NRowsInPattern() const { return rows_in_pattern_; }
95
96 private:
100 AntennaPairFile(const std::string& filename)
101 : file_(BufferedColumnarFile::CreateNew(filename, kHeaderSize, sizeof(int32_t) * 2)) {}
102
107 AntennaPairFile(const std::string& filename, bool /*open existing*/)
109 ReadHeader();
110 ReadData();
111 }
112
113 static bool HasUnsetAntenna(const std::array<int32_t, 2>& pair) {
114 return pair[0] == kUnsetAntenna || pair[1] == kUnsetAntenna;
115 }
116
120 template <size_t AntennaNumber>
121 void WriteAntenna(uint64_t row, int32_t antenna) {
122 static_assert(AntennaNumber == 0 || AntennaNumber == 1);
123 if (rows_in_pattern_ == 0) {
124 const bool has_unfinished_row = !data_.empty() && HasUnsetAntenna(data_.back());
125 if (has_unfinished_row) {
126 if (row >= data_.size())
127 throw std::runtime_error(
128 "Incorrect writing order for AntennaPairFile (in unfinished "
129 "pair, row=" +
130 std::to_string(row) + ")");
131 const bool is_rewrite =
132 row < data_.size() - 1 || data_.back()[AntennaNumber] != kUnsetAntenna;
133 if (is_rewrite) {
134 if (data_[row][AntennaNumber] != antenna)
135 throw std::runtime_error("Antenna " + std::to_string(AntennaNumber) + " value in row " +
136 std::to_string(row) + " is rewritten with a different value");
137 } else {
138 data_.back()[AntennaNumber] = antenna;
139 if (data_.back() == data_.front() && data_.size() > 1) {
140 // This row is the same as the first row, so this row is the first
141 // row of the next repeated pattern, and we have discovered the size
142 // of the pattern.
143 data_.pop_back();
144 rows_in_pattern_ = data_.size();
145 WriteHeader();
146 WriteData();
147 }
148 }
149 } else {
150 if (row > data_.size())
151 throw std::runtime_error(
152 "Incorrect writing order for AntennaPairFile (in new pair, row=" +
153 std::to_string(row) + ")");
154 if (row == data_.size()) {
155 if constexpr (AntennaNumber == 0)
156 data_.emplace_back(std::array<int32_t, 2>{antenna, kUnsetAntenna});
157 else
158 data_.emplace_back(std::array<int32_t, 2>{kUnsetAntenna, antenna});
159 } else {
160 // This is a rewrite of an already written value
161 if (data_[row][AntennaNumber] != antenna)
162 throw std::runtime_error("Antenna " + std::to_string(AntennaNumber) + " value in row " +
163 std::to_string(row) + " is rewritten with a different value");
164 }
165 }
166 } else {
167 const std::array<int32_t, 2>& pair = data_[row % rows_in_pattern_];
168 if (pair[AntennaNumber] != antenna)
169 throw std::runtime_error("Error writing to AntennaPairFile, row " + std::to_string(row) +
170 ": the antenna pairs do not follow a consistent pattern");
171 }
172 }
173
174 template <size_t AntennaNumber>
175 int32_t ReadAntenna(uint64_t row) {
176 static_assert(AntennaNumber == 0 || AntennaNumber == 1);
177 int32_t antenna;
178 if (rows_in_pattern_ == 0) {
179 if (row >= data_.size())
180 throw std::runtime_error(
181 "Invalid read of antenna pair: requested row is beyond the number "
182 "of written rows, and writing of antenna pattern not finished");
183 antenna = data_[row][AntennaNumber];
184 if (antenna == kUnsetAntenna)
185 throw std::runtime_error("Trying to read antenna value that has not been written yet");
186 return antenna;
187 } else {
188 return data_[row % rows_in_pattern_][AntennaNumber];
189 }
190 }
191
192 void ReadHeader() {
193 unsigned char data[kHeaderSize];
194 file_.ReadHeader(data);
195 if (!std::equal(data, data + 8, kMagicHeaderTag)) {
196 throw std::runtime_error(
197 "The Antenna-pair columnar file header does not have the expected "
198 "tag for antenna columns: the measurement set may be damaged");
199 }
200 rows_in_pattern_ = reinterpret_cast<uint64_t&>(data[8]);
201 }
202
203 void WriteHeader() {
204 unsigned char data[kHeaderSize];
205 std::copy_n(kMagicHeaderTag, 8, data);
206 reinterpret_cast<uint64_t&>(data[8]) = rows_in_pattern_;
207 file_.WriteHeader(data);
208 }
209
210 void ReadData() {
211 data_.resize(file_.NRows());
212 for (uint64_t row = 0; row != data_.size(); ++row) {
213 file_.Read(row, 0, data_[row].data(), 2);
214 }
215 }
216
217 void WriteData() {
218 // Note that rows_in_pattern_ might still be zero if the pattern has not
219 // been finished. This would happen if MS is partially written, reopened and
220 // written further. This is rather unlikely to happen, but it is easy to
221 // support.
222 for (uint64_t row = 0; row != data_.size(); ++row) {
223 file_.Write(row, 0, data_[row].data(), 2);
224 }
225 }
226
232 constexpr static size_t kHeaderSize = 16;
233 constexpr static const char kMagicHeaderTag[8] = "AntPair";
234 constexpr static int32_t kUnsetAntenna = std::numeric_limits<int32_t>::min();
239 uint64_t rows_in_pattern_ = 0;
240 std::vector<std::array<int32_t, 2>> data_;
241};
242
243} // namespace casacore
244
245#endif
int32_t ReadAntenna1(uint64_t row)
AntennaPairFile & operator=(AntennaPairFile &&rhs)
void WriteAntenna(uint64_t row, int32_t antenna)
static AntennaPairFile OpenExisting(const std::string &filename)
Open an already existing antenna-pair file from disk with the given filename.
int32_t ReadAntenna(uint64_t row)
std::vector< std::array< int32_t, 2 > > data_
uint64_t NRowsInPattern() const
The number of rows that form one repeating pattern.
void WritePair(uint64_t row, int32_t antenna1, int32_t antenna2)
static constexpr const char kMagicHeaderTag[8]
const std::string & Filename() const
static bool HasUnsetAntenna(const std::array< int32_t, 2 > &pair)
static constexpr size_t kHeaderSize
The header: char[8] "AntPair\0" uint64_t rows_per_block.
AntennaPairFile() noexcept=default
AntennaPairFile(const std::string &filename, bool)
Open an existing file from disk.
BufferedColumnarFile file_
static AntennaPairFile CreateNew(const std::string &filename)
Create a new antenna-pair file on disk with the given filename.
AntennaPairFile(const std::string &filename)
Create a new file on disk.
void WriteAntenna1(uint64_t row, int32_t antenna1)
uint64_t rows_in_pattern_
This value remains zero until the repeating pattern was found.
void WriteAntenna2(uint64_t row, int32_t antenna2)
static constexpr int32_t kUnsetAntenna
int32_t ReadAntenna2(uint64_t row)
For temporary backward namespace compatibility, use casa as alias for casacore.
Definition mainpage.dox:28
void move(TYPE *target, int npixels) const
VarBufferedColumnarFile< 100 *1024 > BufferedColumnarFile
Define real & complex conjugation for non-complex types and put comparisons into std namespace.
Definition Complex.h:344