Skip to content

Commit

Permalink
Merge pull request #126 from paulsengroup/feat/improve-multires-api
Browse files Browse the repository at this point in the history
Improve API of MultiResFile class
  • Loading branch information
robomics authored Nov 12, 2024
2 parents 4c75771 + 96e1ee3 commit 285ffaa
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 4 deletions.
3 changes: 3 additions & 0 deletions docs/api/generic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ Generic API

.. automethod:: __init__
.. automethod:: __getitem__
.. automethod:: attributes
.. automethod:: chromosomes
.. automethod:: is_hic
.. automethod:: is_mcool
.. automethod:: path
.. automethod:: resolutions

Expand Down
42 changes: 42 additions & 0 deletions src/multires_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,43 @@ static std::string repr(const hictk::MultiResFile& mrf) {

static std::filesystem::path get_path(const hictk::MultiResFile& mrf) { return mrf.path(); }

static nb::dict get_attrs(const hictk::hic::File& hf) {
nb::dict py_attrs;

py_attrs["format"] = "HIC";
py_attrs["format-version"] = hf.version();
py_attrs["assembly"] = hf.assembly();
py_attrs["format-url"] = "https://github.com/aidenlab/hic-format";
py_attrs["nchroms"] = hf.nchroms();

for (const auto& [k, v] : hf.attributes()) {
py_attrs[nb::cast(k)] = v;
}

return py_attrs;
}

static nb::dict get_attrs(const hictk::cooler::MultiResFile& mclr) {
nb::dict py_attrs;

py_attrs["format"] = mclr.attributes().format;
py_attrs["format-version"] = mclr.attributes().format_version;
py_attrs["format-url"] = "https://github.com/open2c/cooler";
py_attrs["assembly"] =
mclr.open(mclr.resolutions().front()).attributes().assembly.value_or("unknown");
py_attrs["nchroms"] = mclr.chromosomes().size();

return py_attrs;
}

static nb::dict attributes(const hictk::MultiResFile& f) {
auto attrs = f.is_hic() ? get_attrs(f.open(f.resolutions().front()).get<hictk::hic::File>())
: get_attrs(hictk::cooler::MultiResFile{f.path()});
attrs["resolutions"] = f.resolutions();

return attrs;
}

bool is_mcool_file(const std::filesystem::path& path) {
return bool(hictk::cooler::utils::is_multires_file(path.string()));
}
Expand All @@ -40,12 +77,17 @@ void declare_multires_file_class(nb::module_& m) {
mres_file.def("__repr__", &multires_file::repr, nb::rv_policy::move);

mres_file.def("path", &multires_file::get_path, "Get the file path.", nb::rv_policy::move);
mres_file.def("is_mcool", &hictk::MultiResFile::is_mcool,
"Test whether the file is in .mcool format.");
mres_file.def("is_hic", &hictk::MultiResFile::is_hic, "Test whether the file is in .hic format.");
mres_file.def("chromosomes", &get_chromosomes_from_object<hictk::MultiResFile>,
nb::arg("include_ALL") = false,
"Get chromosomes sizes as a dictionary mapping names to sizes.",
nb::rv_policy::take_ownership);
mres_file.def("resolutions", &hictk::MultiResFile::resolutions,
"Get the list of available resolutions.", nb::rv_policy::copy);
mres_file.def("attributes", &multires_file::attributes, "Get file attributes as a dictionary.",
nb::rv_policy::take_ownership);
mres_file.def("__getitem__", &hictk::MultiResFile::open,
"Open the Cooler or .hic file corresponding to the resolution given as input.",
nb::rv_policy::move);
Expand Down
28 changes: 24 additions & 4 deletions test/test_multires_file_accessors.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,39 @@
testdir = pathlib.Path(__file__).resolve().parent

pytestmark = pytest.mark.parametrize(
"file",
"file,format",
[
testdir / "data" / "cooler_test_file.mcool",
(testdir / "data" / "cooler_test_file.mcool", "mcool"),
(testdir / "data" / "hic_test_file.hic", "hic"),
],
)


class TestClass:
def test_attributes(self, file):
def test_accessors(self, file, format):
f = hictkpy.MultiResFile(file)

assert str(f).startswith("MultiResFile(")

assert f.path() == file
assert f.resolutions() == [100_000, 1_000_000]
assert f.is_mcool() == (format == "mcool")
assert f.is_hic() == (format == "hic")
assert len(f.chromosomes()) == 8

if f.is_hic():
resolutions = [100_000]
assert f.resolutions() == resolutions
assert f.attributes()["format"] == "HIC"
assert f.attributes()["format-version"] == 9
assert f.attributes()["resolutions"] == resolutions
else:
resolutions = [100_000, 1_000_000]
assert f.resolutions() == resolutions
assert f.attributes()["format"] == "HDF5::MCOOL"
assert f.attributes()["format-version"] == 2
assert f.attributes()["resolutions"] == resolutions

assert f[100_000].resolution() == 100_000

with pytest.raises(Exception):
f[1234] # noqa

0 comments on commit 285ffaa

Please sign in to comment.