Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
BUILD_DIR ?= build

# NOTE:
#
# To build profiling versions of the executable targets:
#
# make clean
# CXXFLAGS='-pg -O0' LDFLAGS='-pg' make

.PHONEY: all clean test

all: $(BUILD_DIR)/compile_commands.json
Expand Down
9 changes: 6 additions & 3 deletions bin/mzp-inspect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,9 @@ int print_fmd_kv(MzPeak::Index& index,
}

/******************************************************************************/
int dump_spectra(MzPeak::Index& index)
int dump_spectra(MzPeak::Index& index, MzPeak::Index::SpectraSource source)
{
auto spectra = index.spectra();
auto spectra = index.spectra(source);

for (std::size_t spectrum_index : std::views::iota(0ul, spectra.size())) {
const auto& spectrum = spectra[spectrum_index];
Expand Down Expand Up @@ -188,6 +188,7 @@ int main(int argc, char* argv[])
"Used with --fmdkv to print the value of the given key");

desc.add_options()("spectra", "Print all m/z and intensity values");
desc.add_options()("peaks", "Like --spectra but read from spectra_peaks.parquet");

po::positional_options_description pops;
pops.add("file", 1);
Expand Down Expand Up @@ -225,7 +226,9 @@ int main(int argc, char* argv[])

return print_fmd_kv(index, vmap["fmdkv"].as<std::string>(), key);
} else if (vmap.count("spectra")) {
dump_spectra(index);
dump_spectra(index, MzPeak::Index::SpectraSource::Data);
} else if (vmap.count("peaks")) {
dump_spectra(index, MzPeak::Index::SpectraSource::Peaks);
Comment thread
pjones marked this conversation as resolved.
} else {
std::println("WARN: no command given");
return 1;
Expand Down
24 changes: 23 additions & 1 deletion include/mzpeak/index.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,32 @@ class Index {
std::vector<Schema::File>::const_iterator find_file(Schema::EntityType::Type,
Schema::DataKind::Type) const;

/**
* Indicates which source to fetch spectra data from.
*/
enum class SpectraSource {
/// Use the `spectra_data.parquet` file which may contain profile
/// or centroid spectra data.
Data,

/// Use the `spectra_peaks.parquet` file which is optional and may
/// not exist.
Peaks,
};

/**
* Returns `true` if the give source file exists.
*/
bool has_spectra(SpectraSource) const;

/**
* Access the spectra in the file.
*
* Throws an exception if `SpectraSource::Peaks` is request and does
* not exist. Use the `has_spectra` function to check for a peaks
* source before call this function.
*/
Spectra spectra() const;
Spectra spectra(SpectraSource source = SpectraSource::Data) const;

/**
* Access the low-level MzPeak Manager object.
Expand Down
1 change: 1 addition & 0 deletions include/mzpeak/spectra.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class Spectra final : public Util::EnumerableProxy<Spectrum> {
// Internal data access.
std::shared_ptr<Data::Signals> data_;
std::shared_ptr<Util::Manager> manager_;
std::vector<Data::ArrayIndex::Dimension> default_dims_;

// Function to fetch a specific spectrum.
Spectrum fetch(uint64_t);
Expand Down
36 changes: 21 additions & 15 deletions include/mzpeak/util/enumerable_proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ directory of this repository.

#include <boost/range/detail/common.hpp>
#include <cstddef>
#include <functional>
#include <cstdint>
#include <iterator>
#include <optional>
#include <utility>
Expand All @@ -22,34 +22,33 @@ namespace MzPeak::Util {
template <typename T, typename V = T>
class EnumerableProxy : public std::ranges::view_interface<EnumerableProxy<T>> {
public:
/// A function that can fetch the requested value.
using fetch_t = std::function<V(std::size_t)>;

/// The iterator type.
class Iterator {
public:
using difference_type = std::ptrdiff_t;
using value_type = V;

/// Constructor for a valid iterator.
Iterator(std::size_t n, fetch_t fetch)
Iterator(std::size_t n, EnumerableProxy<T, V>* owner)
: n_(n)
, fetch_(fetch)
, owner_(owner)
, cache_()
{
}

/// Constructor for an invalid iterator.
Iterator(std::size_t n)
: n_(n)
, fetch_(nullptr)
, owner_(nullptr)
, cache_()
{
}

/// Default construction also invalid;
Iterator()
: n_(0)
, owner_(nullptr)
, cache_()
{
}

Expand Down Expand Up @@ -97,8 +96,9 @@ class EnumerableProxy : public std::ranges::view_interface<EnumerableProxy<T>> {
{
if (cache_.has_value() && cache_->first == n_) {
return cache_->second;
} else if (fetch_ != nullptr) {
const_cast<Iterator*>(this)->cache_ = std::make_pair<>(n_, fetch_(n_));
} else if (owner_ != nullptr) {
auto* self = const_cast<Iterator*>(this);
self->cache_ = std::make_pair<>(n_, self->owner_->fetch(n_));
return cache_->second;
} else {
throw InvalidIteratorError("attempt to dereference an invalid iterator");
Expand All @@ -107,7 +107,7 @@ class EnumerableProxy : public std::ranges::view_interface<EnumerableProxy<T>> {

private:
std::size_t n_;
fetch_t fetch_;
EnumerableProxy<T, V>* owner_;
std::optional<std::pair<std::size_t, value_type>> cache_;
};

Expand All @@ -124,31 +124,37 @@ class EnumerableProxy : public std::ranges::view_interface<EnumerableProxy<T>> {
~EnumerableProxy() = default;

/// Meaningful constructor.
EnumerableProxy(std::size_t count, fetch_t fetch)
EnumerableProxy(std::size_t count)
: count_(count)
, fetch_(fetch)
{
}

/// The number of elements.
std::size_t size() const { return count_; }

/// Iterator to the first element.
Iterator begin() const { return Iterator(0, fetch_); }
Iterator begin() const
{
return Iterator(0, const_cast<EnumerableProxy<T, V>*>(this));
}

/// Iterator/sentinel representing one element beyond the last.
Iterator end() const { return Iterator(count_); }

// Access an element by its index.
V operator[](std::size_t n) { return fetch_(n); }
V operator[](std::size_t n) { return fetch(n); }

protected:
friend class Iterator;

/// Update the internal count of records.
void resize(std::size_t n) { count_ = n; }

/// The function to call to get a specific element.
virtual V fetch(uint64_t) = 0;

private:
std::size_t count_ = 0;
fetch_t fetch_ = nullptr;
};

} // namespace MzPeak::Util
30 changes: 27 additions & 3 deletions src/index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ directory of this repository.
*/

#include <memory>
#include <utility>

#include "mzpeak/data/signals.h"
#include "mzpeak/exception.h"
Expand All @@ -17,6 +18,21 @@ directory of this repository.

namespace MzPeak {

/******************************************************************************/
std::string source_to_file_name(Index::SpectraSource source)
{
using enum Index::SpectraSource;

switch (source) {
case Data:
return "spectra_data.parquet";
case Peaks:
return "spectra_peaks.parquet";
}

std::unreachable();
}

/******************************************************************************/
Index::Index(std::unique_ptr<MzPeak::IO::Archive> archive)
: manager_(std::make_shared<Util::Manager>(std::move(archive)))
Expand All @@ -34,12 +50,20 @@ Index::find_file(Schema::EntityType::Type et, Schema::DataKind::Type dk) const
}

/******************************************************************************/
Spectra Index::spectra() const
bool Index::has_spectra(SpectraSource source) const
{
auto data_it = manager_->find_file(source_to_file_name(source));
return data_it != manager_->files().end();
}

/******************************************************************************/
Spectra Index::spectra(SpectraSource source) const
{
auto data_it = manager_->find_file("spectra_data.parquet");
std::string file_name(source_to_file_name(source));
auto data_it = manager_->find_file(file_name);

if (data_it == manager_->files().end()) {
throw InvalidFormatError("missing files: spectra_data.parquet");
throw InvalidFormatError("missing file spectra file: " + file_name);
}

std::unique_ptr<Data::Signals> data =
Expand Down
37 changes: 21 additions & 16 deletions src/spectra.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,11 @@ top-level directory of this repository.
namespace MzPeak {

/******************************************************************************/
Spectra::Spectra(std::unique_ptr<Data::Signals> data,
std::shared_ptr<Util::Manager> manager)
: EnumerableProxy(
0, std::bind(std::mem_fn(&Spectra::fetch), this, std::placeholders::_1))
, data_(std::move(data))
, manager_(std::move(manager))
{
// Update the record count.
resize(data_->record_count());
}

/******************************************************************************/
Spectrum Spectra::fetch(uint64_t index)
std::vector<Data::ArrayIndex::Dimension> initial_dims(const Data::Signals& data)
{
// These are the dimensions we'll project by default.
std::vector<Data::ArrayIndex::Dimension> dims =
data_->array_index()->dimensions() | std::views::filter([](auto& d) {
data.array_index()->dimensions() | std::views::filter([](auto& d) {
return d.array_type == Schema::PSI::ArrayType::Mz ||
d.array_type == Schema::PSI::ArrayType::Intensity;
}) |
Expand All @@ -49,9 +37,26 @@ Spectrum Spectra::fetch(uint64_t index)
});

dims.erase(to_erase.begin(), to_erase.end());
return dims;
}

/******************************************************************************/
Spectra::Spectra(std::unique_ptr<Data::Signals> data,
std::shared_ptr<Util::Manager> manager)
: EnumerableProxy(data->record_count())
, data_(std::move(data))
, manager_(std::move(manager))
, default_dims_(initial_dims(*data_))
{
}

/******************************************************************************/
Spectrum Spectra::fetch(uint64_t index)
{
std::unique_ptr<Util::Slice> slice =
data_->select(default_dims_, data_->index().eq(index));

std::unique_ptr<Util::Slice> slice = data_->select(dims, data_->index().eq(index));
return Spectrum(index, manager_, data_, dims, std::move(slice));
return Spectrum(index, manager_, data_, default_dims_, std::move(slice));
}

} // namespace MzPeak
28 changes: 20 additions & 8 deletions test/util_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,30 @@ directory of this repository.

#include "mzpeak/util/enumerable_proxy.h"

namespace {
struct EPTest : public MzPeak::Util::EnumerableProxy<int, int> {
EPTest()
: EnumerableProxy(0)
{
resize(v.size());
}

std::vector<int> v{0, 1, 2, 3, 4, 5};
int fetch(uint64_t i) { return v[i]; }
};
} // namespace

/******************************************************************************/
BOOST_AUTO_TEST_CASE(enumerable_proxy_simple)
{
std::vector<int> v1{0, 1, 2, 3, 4, 5}, v2;
v2.reserve(v1.size());

MzPeak::Util::EnumerableProxy<int, int> ep(v1.size(),
[v1](std::size_t n) { return v1[n]; });
EPTest ep_test;
std::vector<int> v;
v.reserve(ep_test.v.size());

for (auto i : ep) {
v2.push_back(i);
for (auto i : ep_test) {
v.push_back(i);
}

BOOST_TEST(v1 == v2);
BOOST_TEST(ep_test.v.size() == v.size());
Comment thread
pjones marked this conversation as resolved.
BOOST_TEST(ep_test.v == v);
}