-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1 parent
6bdbc7b
commit 7f74499
Showing
24 changed files
with
1,379 additions
and
522 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
import numpy as np | ||
from .adelie_core import io as core_io | ||
|
||
|
||
class snp_unphased: | ||
"""IO handler for SNP Unphased data. | ||
Parameters | ||
---------- | ||
filename : str | ||
File name to either read from or write to related to the SNP data. | ||
""" | ||
def __init__( | ||
self, | ||
filename, | ||
): | ||
self._core = core_io.IOSNPUnphased(filename) | ||
|
||
def endian(self): | ||
"""Gets the endianness used in the file. | ||
Returns | ||
------- | ||
endian : str | ||
``"big-endian"`` if big-endian and ``"little-endian"`` if little-endian. | ||
""" | ||
return ( | ||
"big-endian" | ||
if self._core.endian() else | ||
"little-endian" | ||
) | ||
|
||
def rows(self): | ||
"""Gets the number of rows of the matrix. | ||
Returns | ||
------- | ||
rows : int | ||
Number of rows. | ||
""" | ||
return self._core.rows() | ||
|
||
def cols(self): | ||
"""Gets the number of columns of the matrix. | ||
Returns | ||
------- | ||
cols : int | ||
Number of columns. | ||
""" | ||
return self._core.cols() | ||
|
||
def outer(self): | ||
"""Gets the outer indexing vector. | ||
Returns | ||
------- | ||
outer : (p+1,) np.ndarray | ||
Outer indexing vector. | ||
""" | ||
return self._core.outer() | ||
|
||
def nnz(self, j: int): | ||
"""Gets the number of non-zero entries at a column. | ||
Parameters | ||
---------- | ||
j : int | ||
Column index. | ||
Returns | ||
------- | ||
nnz : int | ||
Number of non-zero entries column ``j``. | ||
""" | ||
return self._core.nnz(j) | ||
|
||
def inner(self, j: int): | ||
"""Gets the inner indexing vector at a column. | ||
Parameters | ||
---------- | ||
j : int | ||
Column index. | ||
Returns | ||
------- | ||
inner : np.ndarray | ||
Inner indexing vector at column ``j``. | ||
""" | ||
return self._core.inner(j) | ||
|
||
def value(self, j: int): | ||
"""Gets the value vector at a column. | ||
Parameters | ||
---------- | ||
j : int | ||
Column index. | ||
Returns | ||
------- | ||
v : np.ndarray | ||
Value vector at column ``j``. | ||
""" | ||
return self._core.value(j) | ||
|
||
def to_dense(self, n_threads: int =1): | ||
"""Creates a dense matrix. | ||
Parameters | ||
---------- | ||
n_threads : int, optional | ||
Number of threads. | ||
Default is ``1``. | ||
Returns | ||
------- | ||
dense : (n, p) np.ndarray | ||
Dense matrix. | ||
""" | ||
return self._core.to_dense(n_threads) | ||
|
||
def read(self): | ||
"""Read and load the matrix from file. | ||
Returns | ||
------- | ||
total_bytes : int | ||
Number of bytes read. | ||
""" | ||
return self._core.read() | ||
|
||
def write( | ||
self, | ||
calldata: np.ndarray, | ||
n_threads: int =1, | ||
): | ||
"""Write dense array to the file in special format. | ||
Parameters | ||
---------- | ||
calldata : (n, p) np.ndarray | ||
SNP unphased calldata in dense format. | ||
n_threads : int, optional | ||
Number of threads. | ||
Default is ``1``. | ||
Returns | ||
------- | ||
total_bytes : int | ||
Number of bytes written. | ||
""" | ||
return self._core.write(calldata, n_threads) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,263 @@ | ||
#pragma once | ||
#include <string> | ||
#include <cstdio> | ||
#include <functional> | ||
#include <memory> | ||
#include <iostream> | ||
#include <adelie_core/util/types.hpp> | ||
|
||
namespace adelie_core { | ||
namespace io { | ||
|
||
class IOSNPUnphased | ||
{ | ||
public: | ||
using string_t = std::string; | ||
using file_unique_ptr_t = std::unique_ptr< | ||
std::FILE, | ||
std::function<void(std::FILE*)> | ||
>; | ||
using bool_t = bool; | ||
using outer_t = uint64_t; | ||
using inner_t = uint32_t; | ||
using value_t = int8_t; | ||
using vec_outer_t = util::rowvec_type<outer_t>; | ||
using vec_inner_t = util::rowvec_type<inner_t>; | ||
using vec_value_t = util::rowvec_type<value_t>; | ||
using buffer_t = util::rowvec_type<char>; | ||
using rowarr_value_t = util::rowarr_type<int8_t>; | ||
|
||
protected: | ||
static constexpr size_t _multiplier = ( | ||
sizeof(inner_t) + | ||
sizeof(value_t) | ||
); | ||
|
||
const string_t _filename; | ||
buffer_t _buffer; | ||
bool_t _is_read; | ||
|
||
static void throw_no_read() | ||
{ | ||
throw std::runtime_error( | ||
"File is not read yet. Call read() first." | ||
); | ||
} | ||
|
||
static auto fopen_safe( | ||
const char* filename, | ||
const char* mode | ||
) | ||
{ | ||
file_unique_ptr_t file_ptr( | ||
std::fopen(filename, mode), | ||
[](std::FILE* fp) { std::fclose(fp); } | ||
); | ||
auto fp = file_ptr.get(); | ||
if (!fp) { | ||
throw std::runtime_error("Cannot open file " + std::string(filename)); | ||
} | ||
return file_ptr; | ||
} | ||
|
||
static bool is_big_endian() | ||
{ | ||
union { | ||
uint32_t i; | ||
char c[4]; | ||
} _bint = {0x01020304}; | ||
|
||
return _bint.c[0] == 1; | ||
} | ||
|
||
public: | ||
IOSNPUnphased( | ||
const string_t& filename | ||
): | ||
_filename(filename), | ||
_buffer(), | ||
_is_read(false) | ||
{} | ||
|
||
bool_t endian() const { | ||
if (!_is_read) throw_no_read(); | ||
return reinterpret_cast<const bool_t&>(_buffer[0]); | ||
} | ||
|
||
inner_t rows() const { | ||
if (!_is_read) throw_no_read(); | ||
return reinterpret_cast<const inner_t&>(_buffer[sizeof(bool_t)]); | ||
} | ||
|
||
inner_t cols() const | ||
{ | ||
if (!_is_read) throw_no_read(); | ||
return reinterpret_cast<const inner_t&>(_buffer[sizeof(bool_t) + sizeof(inner_t)]); | ||
} | ||
|
||
Eigen::Ref<const vec_outer_t> outer() const | ||
{ | ||
if (!_is_read) throw_no_read(); | ||
return Eigen::Map<const vec_outer_t>( | ||
reinterpret_cast<const outer_t*>(&_buffer[sizeof(bool_t) + 2 * sizeof(inner_t)]), | ||
cols() + 1 | ||
); | ||
} | ||
|
||
inner_t nnz(int j) const | ||
{ | ||
if (!_is_read) throw_no_read(); | ||
const auto _outer = outer(); | ||
return (_outer[j+1] - _outer[j]) / _multiplier; | ||
} | ||
|
||
Eigen::Ref<const vec_inner_t> inner(int j) const | ||
{ | ||
if (!_is_read) throw_no_read(); | ||
const auto _outer = outer(); | ||
return Eigen::Map<const vec_inner_t>( | ||
reinterpret_cast<const inner_t*>(&_buffer[_outer[j]]), | ||
nnz(j) | ||
); | ||
} | ||
|
||
Eigen::Ref<const vec_value_t> value(int j) const | ||
{ | ||
if (!_is_read) throw_no_read(); | ||
const auto _outer = outer(); | ||
const auto _nnz = nnz(j); | ||
return Eigen::Map<const vec_value_t>( | ||
reinterpret_cast<const value_t*>(&_buffer[_outer[j] + sizeof(inner_t) * _nnz]), | ||
_nnz | ||
); | ||
} | ||
|
||
rowarr_value_t to_dense( | ||
size_t n_threads | ||
) const | ||
{ | ||
if (!_is_read) throw_no_read(); | ||
const auto n = rows(); | ||
const auto p = cols(); | ||
rowarr_value_t dense(n, p); | ||
|
||
n_threads = std::min<size_t>(n_threads, p); | ||
#pragma omp parallel for schedule(auto) num_threads(n_threads) | ||
for (inner_t j = 0; j < p; ++j) { | ||
const auto _inner = inner(j); | ||
const auto _value = value(j); | ||
auto dense_j = dense.col(j); | ||
dense_j.setZero(); | ||
for (inner_t i = 0; i < _inner.size(); ++i) { | ||
dense_j[_inner[i]] = _value[i]; | ||
} | ||
} | ||
|
||
return dense; | ||
} | ||
|
||
size_t read() | ||
{ | ||
_is_read = true; | ||
|
||
auto file_ptr = fopen_safe(_filename.c_str(), "rb"); | ||
auto fp = file_ptr.get(); | ||
std::fseek(fp, 0, SEEK_END); | ||
const size_t total_bytes = std::ftell(fp); | ||
|
||
_buffer.resize(total_bytes); | ||
std::fseek(fp, 0, SEEK_SET); | ||
const size_t read = std::fread(_buffer.data(), sizeof(char), _buffer.size(), fp); | ||
if (read != _buffer.size()) { | ||
throw std::runtime_error( | ||
"Could not read the whole file into buffer." | ||
); | ||
} | ||
|
||
bool endian = _buffer[0]; | ||
if (endian != is_big_endian()) { | ||
throw std::runtime_error( | ||
"Endianness is inconsistent! " | ||
"Regenerate the file on a machine with the same endianness." | ||
); | ||
} | ||
|
||
return total_bytes; | ||
} | ||
|
||
size_t write( | ||
const Eigen::Ref<const rowarr_value_t>& calldata, | ||
size_t n_threads | ||
) | ||
{ | ||
const bool_t endian = is_big_endian(); | ||
const inner_t n = calldata.rows(); | ||
const inner_t p = calldata.cols(); | ||
|
||
// outer[i] = number of bytes to jump from beginning of file | ||
// to start reading column i information. | ||
// outer[i+1] - outer[i] = total number of bytes for column i. | ||
vec_outer_t outer(p+1); | ||
outer[0] = 0; | ||
outer.tail(p) = (calldata != 0).colwise().count().template cast<outer_t>(); | ||
for (int i = 1; i < outer.size(); ++i) { | ||
outer[i] += outer[i-1]; | ||
} | ||
outer *= _multiplier; | ||
outer += ( | ||
sizeof(bool_t) + | ||
2 * sizeof(inner_t) + | ||
outer.size() * sizeof(outer_t) | ||
); | ||
|
||
auto& buffer = _buffer; | ||
buffer.resize(outer[p]); | ||
|
||
size_t idx = 0; | ||
reinterpret_cast<bool_t&>(buffer[idx]) = endian; idx += sizeof(bool_t); | ||
reinterpret_cast<inner_t&>(buffer[idx]) = n; idx += sizeof(inner_t); | ||
reinterpret_cast<inner_t&>(buffer[idx]) = p; idx += sizeof(inner_t); | ||
Eigen::Map<vec_outer_t>( | ||
reinterpret_cast<outer_t*>(&buffer[idx]), | ||
outer.size() | ||
) = outer; | ||
|
||
n_threads = std::min<size_t>(n_threads, p); | ||
#pragma omp parallel for schedule(auto) num_threads(n_threads) | ||
for (inner_t j = 0; j < p; ++j) { | ||
const auto col_j = calldata.col(j); | ||
const auto nnz_bytes = outer[j+1] - outer[j]; | ||
const auto nnz = nnz_bytes / _multiplier; | ||
Eigen::Map<vec_inner_t> inner( | ||
reinterpret_cast<inner_t*>(&buffer[outer[j]]), | ||
nnz | ||
); | ||
Eigen::Map<vec_value_t> value( | ||
reinterpret_cast<value_t*>(&buffer[outer[j] + sizeof(inner_t) * nnz]), | ||
nnz | ||
); | ||
|
||
size_t count = 0; | ||
for (int i = 0; i < n; ++i) { | ||
if (col_j[i] == 0) continue; | ||
inner[count] = i; | ||
value[count] = col_j[i]; | ||
++count; | ||
} | ||
} | ||
|
||
auto file_ptr = fopen_safe(_filename.c_str(), "wb"); | ||
auto fp = file_ptr.get(); | ||
auto total_bytes = std::fwrite(buffer.data(), sizeof(char), buffer.size(), fp); | ||
if (total_bytes != buffer.size()) { | ||
throw std::runtime_error( | ||
"Could not write the full buffer." | ||
); | ||
} | ||
|
||
return total_bytes; | ||
} | ||
}; | ||
|
||
} // namespace io | ||
} // namespace adelie_core |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#include "decl.hpp" | ||
#include <adelie_core/io/io_snp_unphased.hpp> | ||
|
||
namespace py = pybind11; | ||
namespace ad = adelie_core; | ||
|
||
void io_snp_unphased(py::module_& m) | ||
{ | ||
using io_t = ad::io::IOSNPUnphased; | ||
py::class_<io_t>(m, "IOSNPUnphased") | ||
.def(py::init<std::string>(), | ||
py::arg("filename") | ||
) | ||
.def("endian", &io_t::endian) | ||
.def("rows", &io_t::rows) | ||
.def("cols", &io_t::cols) | ||
.def("outer", &io_t::outer) | ||
.def("nnz", &io_t::nnz) | ||
.def("inner", &io_t::inner) | ||
.def("value", &io_t::value) | ||
.def("to_dense", &io_t::to_dense) | ||
.def("read", &io_t::read) | ||
.def("write", &io_t::write, | ||
py::arg("calldata").noconvert(), | ||
py::arg("n_threads") | ||
) | ||
; | ||
} | ||
|
||
void register_io(py::module_& m) | ||
{ | ||
io_snp_unphased(m); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# __SNP IO Examples__" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 1, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"%load_ext autoreload\n", | ||
"%autoreload 2" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 2, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import adelie as ad\n", | ||
"import numpy as np\n", | ||
"import os" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## __SNP Unphased__" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 3, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"n = 400000\n", | ||
"ps = [10, 20, 30]\n", | ||
"seed = 0\n", | ||
"\n", | ||
"filenames = [\n", | ||
" f\"/tmp/dummy_{i}.snpdat\"\n", | ||
" for i in range(len(ps))\n", | ||
"]\n", | ||
"\n", | ||
"np.random.seed(seed)\n", | ||
"calldatas = [\n", | ||
" ad.data.create_snp_unphased(n, pi, seed=i)[\"X\"]\n", | ||
" for i, pi in enumerate(ps)\n", | ||
"]\n", | ||
"calldata = np.concatenate(calldatas, axis=-1)\n", | ||
"\n", | ||
"for name, dat in zip(filenames, calldatas):\n", | ||
" handler = ad.io.snp_unphased(name)\n", | ||
" handler.write(dat, n_threads=4)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 114, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"mat = ad.matrix.snp_unphased(filenames, n_threads=8)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 115, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"w = np.random.uniform(1, 2, n)\n", | ||
"w /= np.sum(w)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 127, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"j = 0\n", | ||
"q = 1\n", | ||
"v = np.random.normal(0, 1, q)\n", | ||
"out = np.empty(n)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 132, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"CPU times: user 374 µs, sys: 0 ns, total: 374 µs\n", | ||
"Wall time: 381 µs\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"%%time\n", | ||
"mat.btmul(j, q, v, w, out)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 126, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"CPU times: user 29.6 ms, sys: 0 ns, total: 29.6 ms\n", | ||
"Wall time: 12.2 ms\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"%%time\n", | ||
"expected = (v.T @ (w[:, None] * calldata[:, j:j+q]).T)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 101, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/plain": [ | ||
"True" | ||
] | ||
}, | ||
"execution_count": 101, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"np.allclose(out, expected)" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "adelie", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.10.12" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,5 +6,4 @@ User Guide | |
:maxdepth: 1 | ||
|
||
|
||
notebooks/edpp_study | ||
notebooks/pivot_rule |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import adelie as ad | ||
import numpy as np | ||
import os | ||
|
||
|
||
def create_calldata( | ||
n, p, seed | ||
): | ||
np.random.seed(seed) | ||
calldata = np.zeros((n, p), dtype=np.int8) | ||
calldata.ravel()[ | ||
np.random.choice(np.arange(n * p), int(0.25 * n * p), replace=False) | ||
] = 1 | ||
calldata.ravel()[ | ||
np.random.choice(np.arange(n * p), int(0.05 * n * p), replace=False) | ||
] = 2 | ||
return calldata | ||
|
||
|
||
def test_io_snp_unphased(): | ||
def _test(n, p, seed=0): | ||
calldata = create_calldata(n, p, seed) | ||
|
||
filename = "/tmp/dummy_snp_unphased.snpdat" | ||
handler = ad.io.snp_unphased(filename) | ||
w_bytes = handler.write(calldata) | ||
r_bytes = handler.read() | ||
os.remove(filename) | ||
|
||
total_bytes_exp = ( | ||
1 + 2 * 4 + 8 * (p + 1) + 5 * np.sum(calldata != 0) | ||
) | ||
assert w_bytes == total_bytes_exp | ||
assert w_bytes == r_bytes | ||
assert handler.rows() == n | ||
assert handler.cols() == p | ||
|
||
outer = handler.outer() | ||
nnzs = np.array([handler.nnz(j) for j in range(p)]) | ||
inners = [handler.inner(j) for j in range(p)] | ||
values = [handler.value(j) for j in range(p)] | ||
|
||
assert np.allclose((outer[1:] - outer[:-1]) / 5, nnzs) | ||
for j in range(p): | ||
assert np.allclose( | ||
np.arange(n)[calldata[:, j] != 0], | ||
inners[j], | ||
) | ||
assert np.allclose( | ||
calldata[:, j][calldata[:, j] != 0], | ||
values[j], | ||
) | ||
|
||
dense = handler.to_dense() | ||
assert np.allclose(dense, calldata) | ||
|
||
_test(1, 1) | ||
_test(200, 32) | ||
_test(2000, 3000) | ||
_test(1421, 927) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters