38 [[nodiscard]]
unsigned checked_sample_count(
const std::size_t sample_count,
const std::string_view source)
40 if (sample_count >
static_cast<std::size_t
>(std::numeric_limits<unsigned>::max()))
42 throw std::runtime_error(std::format(
"Waveform '{}' has too many samples to load into Signal.", source));
44 return static_cast<unsigned>(sample_count);
47 [[nodiscard]]
unsigned parse_csv_sample_count(
const RealType sample_count,
const std::filesystem::path& filepath)
49 if (!std::isfinite(sample_count) || sample_count < 0.0 || std::trunc(sample_count) != sample_count)
51 throw std::runtime_error(
"Waveform file '" + filepath.string() +
"' has an invalid sample count header.");
54 if (sample_count >
static_cast<RealType>(std::numeric_limits<unsigned>::max()))
56 throw std::runtime_error(
"Waveform file '" + filepath.string() +
57 "' declares more samples than Signal can represent.");
60 return static_cast<unsigned>(sample_count);
73 std::unique_ptr<RadarSignal> loadWaveformFromHdf5File(
const std::string& name,
74 const std::filesystem::path& filepath,
const RealType power,
77 std::vector<ComplexType> data;
79 const unsigned sample_count = checked_sample_count(data.size(), filepath.string());
81 auto signal = std::make_unique<Signal>();
83 return std::make_unique<RadarSignal>(
84 name, power, carrierFreq,
static_cast<RealType>(sample_count) /
params::rate(), std::move(signal),
id);
97 std::unique_ptr<RadarSignal> loadWaveformFromCsvFile(
const std::string& name,
const std::filesystem::path& filepath,
101 std::ifstream ifile(filepath);
105 throw std::runtime_error(
"Could not open file '" + filepath.string() +
"' to read waveform");
110 if (!(ifile >> rlength >> rate))
113 throw std::runtime_error(
"Could not read waveform header from file '" + filepath.string() +
"'");
115 if (!std::isfinite(rate) || rate <= 0.0)
118 throw std::runtime_error(
"Waveform file '" + filepath.string() +
"' has an invalid sample rate");
121 const unsigned length = parse_csv_sample_count(rlength, filepath);
122 std::vector<ComplexType> data(length);
125 for (std::size_t done = 0; done < length && ifile >> data[done]; ++done)
129 if (ifile.fail() || data.size() != length)
132 throw std::runtime_error(
"Could not read full waveform from file '" + filepath.string() +
"'");
135 auto signal = std::make_unique<Signal>();
136 signal->load(data, length, rate);
137 return std::make_unique<RadarSignal>(name, power, carrierFreq, rlength / rate, std::move(signal),
id);
147 constexpr bool hasExtension(
const std::string_view filename,
const std::string_view ext)
noexcept
149 return filename.ends_with(ext);
158 const std::filesystem::path filepath = filename;
159 const auto extension = filepath.extension().string();
161 if (hasExtension(extension,
".csv"))
163 auto wave = loadWaveformFromCsvFile(name, filepath, power, carrierFreq,
id);
164 wave->setFilename(filename);
167 if (hasExtension(extension,
".h5"))
169 auto wave = loadWaveformFromHdf5File(name, filepath, power, carrierFreq,
id);
170 wave->setFilename(filename);
175 throw std::runtime_error(
"Unrecognized file extension '" + extension +
"' for file: " + filename);
Class representing a radar signal with associated properties.
Class for handling radar waveform signal data.
Global configuration file for the project.
double RealType
Type for real numbers.
Header file for HDF5 data export and import functions.
@ FATAL
Fatal level for severe error events.
RealType rate() noexcept
Get the rendering sample rate.
std::unique_ptr< RadarSignal > loadWaveformFromFile(const std::string &name, const std::string &filename, const RealType power, const RealType carrierFreq, const SimId id)
Loads a radar waveform from a file and returns a RadarSignal object.
void readPulseData(const std::string &name, std::vector< ComplexType > &data)
Reads pulse data from an HDF5 file.
Defines the Parameters struct and provides methods for managing simulation parameters.
Classes for handling radar waveforms and signals.
uint64_t SimId
64-bit Unique Simulation ID.