Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
23f23b8
test: migrate featomic to metatensor v0.2.0 (labels-values-array-clean)
HaoZeke Apr 6, 2026
0f3cc3d
fix: LabelValue is now i32 alias -- remove ::new(), .usize(), .i32(),…
HaoZeke Apr 6, 2026
7ae25fa
fix: escape # in tox.ini git URLs to prevent comment stripping
HaoZeke Apr 6, 2026
f465dba
fix: adapt to LabelValue=i32 -- dereference iter_fixed_size, cast usi…
HaoZeke Apr 6, 2026
b687292
fix: comprehensive LabelValue=i32 migration -- deref, casts, Array trait
HaoZeke Apr 6, 2026
a28d944
fix: deref center_type_key in atomic_composition comparison
HaoZeke Apr 6, 2026
aab28af
fix: test code -- deref &i32, ArcArray comparisons, usize casts
HaoZeke Apr 6, 2026
6e81916
fix: to_array -> to_ndarray in lode-madelung integration test
HaoZeke Apr 6, 2026
5370ce7
fix: integration tests -- to_array->to_ndarray, keys_to_* fill_value arg
HaoZeke Apr 6, 2026
c6a834e
fix: soap-power-spectrum test -- ArcArray compat, deref atom
HaoZeke Apr 6, 2026
9009d56
fix: integration tests -- ArcArray comparison, atom deref, fill_value
HaoZeke Apr 6, 2026
c97f7ed
fix: use real ArcArray for fill_value instead of EmptyArray (panics o…
HaoZeke Apr 6, 2026
996175c
fix: cmake FetchContent points to labels-values-array-clean branch fo…
HaoZeke Apr 6, 2026
e96259f
fix: c_api/calculator.rs -- migrate to opaque mts_labels_t (clone ins…
HaoZeke Apr 6, 2026
114cb67
fix: c_api -- unsafe blocks for Labels::from_raw, correct Error::Exte…
HaoZeke Apr 6, 2026
882cb23
fix: bump METATENSOR_REQUIRED_VERSION to 0.2 for cmake find_package c…
HaoZeke Apr 6, 2026
bb0e1ee
fix: featomic.hpp -- mts_labels_t fields to const pointers (opaque type)
HaoZeke Apr 6, 2026
aafa3f5
fix: cxx tests -- DLPackArray to NDArray conversion for comparisons
HaoZeke Apr 6, 2026
cae02ca
fix: cxx test -- SimpleDataArray<double> template param
HaoZeke Apr 6, 2026
dbbc7a3
fix: unique_ptr<SimpleDataArray<double>> template
HaoZeke Apr 6, 2026
9cbda63
fix: c-calculator segfault -- keep DLPack handle alive while using da…
HaoZeke Apr 6, 2026
65022d4
fix: c-calculator -- copy DLPack data into vector before handle clean…
HaoZeke Apr 6, 2026
a15b552
debug: add error logging to query_labels DLPack export
HaoZeke Apr 6, 2026
f3bb06d
fix: use DLPACK_MAJOR/MINOR_VERSION constants for correct DLPack vers…
HaoZeke Apr 7, 2026
d50a353
fix: free labels after mts_block/mts_tensormap (borrow, not own)
HaoZeke Apr 7, 2026
758f35b
fix: C examples -- proper scalar fill_value for keys_to_samples/prope…
HaoZeke Apr 7, 2026
7d3a11f
fix: proper empty_labels_array for mts_labels_create (needs shape cal…
HaoZeke Apr 7, 2026
42a4a3e
fix: add as_dlpack to scalar_fill_value (needed by create callback)
HaoZeke Apr 7, 2026
4ad7260
chore(lint): apply
HaoZeke Apr 7, 2026
3ca5b40
Revert "chore(lint): apply"
HaoZeke Apr 7, 2026
ca9b6de
fix: use metatensor::dlpk re-export instead of direct dlpk dependency
HaoZeke Apr 8, 2026
4cd511f
fix: remove backslash escaping from tox.ini git URLs (breaks subdirec…
HaoZeke Apr 8, 2026
9a07479
fix: CI clones metatensor branch locally instead of git URLs in tox
HaoZeke Apr 8, 2026
ae00d1c
fix: don't pre-install metatensor-torch (C++ build broken on branch, …
HaoZeke Apr 8, 2026
c3777d4
fix: sitepackages=true to inherit pre-installed metatensor, fix Rust …
HaoZeke Apr 8, 2026
9182b3a
fix: disable CI jobs that need metatensor-torch C++ (branch has compi…
HaoZeke Apr 8, 2026
eb75c95
fix: install all metatensor packages from branch clone (including tor…
HaoZeke Apr 8, 2026
6185506
fix: add setuptools to CI pre-install, fetch metatensor-torch from br…
HaoZeke Apr 8, 2026
483a4c2
fix: install torch before metatensor-torch in CI pre-install
HaoZeke Apr 8, 2026
be3678f
ci: retrigger with metatensor cmake version fix
HaoZeke Apr 8, 2026
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
3 changes: 2 additions & 1 deletion .github/workflows/build-wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ on:
push:
branches: [main]
tags: ["*"]
pull_request:
# Disabled for test/metatensor-v0.2.0: packaging requires released metatensor
# pull_request:
paths:
# build wheels in PR if this file changed
- '.github/workflows/build-wheels.yml'
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ jobs:
python -m pip install --upgrade pip
python -m pip install tox coverage

- name: install metatensor from labels-values-array-clean branch
run: |
pip install setuptools cmake packaging wheel
git clone --depth 1 --branch labels-values-array-clean https://github.com/HaoZeke/metatensor.git ${{ runner.temp }}/metatensor-v020
METATENSOR_NO_LOCAL_DEPS=1 pip install --no-build-isolation ${{ runner.temp }}/metatensor-v020/python/metatensor_core
METATENSOR_NO_LOCAL_DEPS=1 pip install --no-build-isolation ${{ runner.temp }}/metatensor-v020/python/metatensor_operations
METATENSOR_NO_LOCAL_DEPS=1 pip install --no-build-isolation ${{ runner.temp }}/metatensor-v020/python/metatensor_learn
pip install torch
METATENSOR_NO_LOCAL_DEPS=1 pip install --no-build-isolation ${{ runner.temp }}/metatensor-v020/python/metatensor_torch
env:
PIP_EXTRA_INDEX_URL: https://download.pytorch.org/whl/cpu

- name: install lcov
run: sudo apt install -y lcov

Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@ jobs:
python -m pip install tox
sudo apt install doxygen

- name: install metatensor from labels-values-array-clean branch
run: |
pip install setuptools cmake packaging wheel
git clone --depth 1 --branch labels-values-array-clean https://github.com/HaoZeke/metatensor.git ${{ runner.temp }}/metatensor-v020
METATENSOR_NO_LOCAL_DEPS=1 pip install --no-build-isolation ${{ runner.temp }}/metatensor-v020/python/metatensor_core
METATENSOR_NO_LOCAL_DEPS=1 pip install --no-build-isolation ${{ runner.temp }}/metatensor-v020/python/metatensor_operations
METATENSOR_NO_LOCAL_DEPS=1 pip install --no-build-isolation ${{ runner.temp }}/metatensor-v020/python/metatensor_learn
pip install torch
METATENSOR_NO_LOCAL_DEPS=1 pip install --no-build-isolation ${{ runner.temp }}/metatensor-v020/python/metatensor_torch
env:
PIP_EXTRA_INDEX_URL: https://download.pytorch.org/whl/cpu

- name: build documentation
run: tox -e docs
env:
Expand Down
13 changes: 12 additions & 1 deletion .github/workflows/python-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ jobs:
python -m pip install --upgrade pip
python -m pip install tox

- name: install metatensor from labels-values-array-clean branch
run: |
pip install setuptools cmake packaging wheel
git clone --depth 1 --branch labels-values-array-clean https://github.com/HaoZeke/metatensor.git ${{ runner.temp }}/metatensor-v020
METATENSOR_NO_LOCAL_DEPS=1 pip install --no-build-isolation ${{ runner.temp }}/metatensor-v020/python/metatensor_core
METATENSOR_NO_LOCAL_DEPS=1 pip install --no-build-isolation ${{ runner.temp }}/metatensor-v020/python/metatensor_operations
METATENSOR_NO_LOCAL_DEPS=1 pip install --no-build-isolation ${{ runner.temp }}/metatensor-v020/python/metatensor_learn
pip install torch
METATENSOR_NO_LOCAL_DEPS=1 pip install --no-build-isolation ${{ runner.temp }}/metatensor-v020/python/metatensor_torch
env:
PIP_EXTRA_INDEX_URL: https://download.pytorch.org/whl/cpu

- name: Setup sccache
uses: mozilla-actions/sccache-action@v0.0.9
with:
Expand All @@ -62,7 +74,6 @@ jobs:
# Use the CPU only version of torch when building/running the code
PIP_EXTRA_INDEX_URL: https://download.pytorch.org/whl/cpu

# second set of jobs checking that (non-test) code still compiles/run as expected
prevent-bitrot:
runs-on: ${{ matrix.os }}
name: Python ${{ matrix.python-version }} / check build
Expand Down
12 changes: 6 additions & 6 deletions featomic-torch/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,17 +122,17 @@ find_package(Torch 2.3 REQUIRED)
#
# When updating METATENSOR_TORCH_FETCH_VERSION, you will also have to update the
# SHA256 sum of the file in `FetchContent_Declare`.
set(METATENSOR_TORCH_FETCH_VERSION "0.8.2")
set(REQUIRED_METATENSOR_TORCH_VERSION "0.8")
set(METATENSOR_TORCH_FETCH_VERSION "0.9.0")
set(REQUIRED_METATENSOR_TORCH_VERSION "0.9")
if (FEATOMIC_FETCH_METATENSOR_TORCH)
message(STATUS "Fetching metatensor-torch from github")
message(STATUS "Fetching metatensor-torch from github (labels-values-array-clean)")

set(URL_ROOT "https://github.com/metatensor/metatensor/releases/download")
include(FetchContent)
FetchContent_Declare(
metatensor_torch
URL ${URL_ROOT}/metatensor-torch-v${METATENSOR_TORCH_FETCH_VERSION}/metatensor-torch-cxx-${METATENSOR_TORCH_FETCH_VERSION}.tar.gz
URL_HASH SHA256=0be618d0cdcfca86cd0c25f47d360b6a2410ebb09ece8d21f153e933ce64bb55
GIT_REPOSITORY https://github.com/HaoZeke/metatensor.git
GIT_TAG labels-values-array-clean
SOURCE_SUBDIR metatensor-torch
)

FetchContent_MakeAvailable(metatensor_torch)
Expand Down
12 changes: 6 additions & 6 deletions featomic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -246,17 +246,17 @@ endif()
#
# When updating METATENSOR_FETCH_VERSION, you will also have to update the
# SHA256 sum of the file in `FetchContent_Declare`.
set(METATENSOR_FETCH_VERSION "0.1.20")
set(METATENSOR_REQUIRED_VERSION "0.1")
set(METATENSOR_FETCH_VERSION "0.2.0")
set(METATENSOR_REQUIRED_VERSION "0.2")
if (FEATOMIC_FETCH_METATENSOR)
message(STATUS "Fetching metatensor-core from github")
message(STATUS "Fetching metatensor-core from github (labels-values-array-clean branch)")

include(FetchContent)
set(URL_ROOT "https://github.com/metatensor/metatensor/releases/download")
FetchContent_Declare(
metatensor
URL ${URL_ROOT}/metatensor-core-v${METATENSOR_FETCH_VERSION}/metatensor-core-cxx-${METATENSOR_FETCH_VERSION}.tar.gz
URL_HASH SHA256=eec78853aa8d2e91d931712242566f8ad3c03cbd291c852fb67a166bfa2e0eaa
GIT_REPOSITORY https://github.com/HaoZeke/metatensor.git
GIT_TAG labels-values-array-clean
SOURCE_SUBDIR metatensor-core
)

FetchContent_MakeAvailable(metatensor)
Expand Down
4 changes: 2 additions & 2 deletions featomic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ metatensor-static = ["metatensor/static"]
all-features = true

[dependencies]
metatensor = {version = "0.2.2", features = ["rayon"]}
metatensor = {git = "https://github.com/HaoZeke/metatensor.git", branch = "labels-values-array-clean", features = ["rayon"]}

ndarray = {version = "0.17", features = ["rayon", "serde", "approx"]}
num-traits = "0.2"
Expand Down Expand Up @@ -57,7 +57,7 @@ toml_writer = "=1.0.2"
[build-dependencies]
cbindgen = { version = "0.29", default-features = false }
fs_extra = "1"
metatensor = "0.2"
metatensor = {git = "https://github.com/HaoZeke/metatensor.git", branch = "labels-values-array-clean"}

# the last versions that supports Rust 1.74
tempfile = "=3.24.0"
Expand Down
138 changes: 118 additions & 20 deletions featomic/examples/compute-soap.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,93 @@
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <featomic.h>
#include <metatensor.h>

#include "common/systems.h"

// Minimal scalar fill_value array for keys_to_samples/keys_to_properties.
static double SCALAR_FILL_DATA = 0.0;
static uintptr_t SCALAR_FILL_SHAPE = 1;

static mts_status_t fill_shape(const void* p, const uintptr_t** shape, uintptr_t* count) {
(void)p; *shape = &SCALAR_FILL_SHAPE; *count = 1; return MTS_SUCCESS;
}
static mts_status_t fill_origin(const void* p, mts_data_origin_t* o) {
(void)p; mts_register_data_origin("c-scalar-fill", o); return MTS_SUCCESS;
}
static mts_status_t fill_device(const void* p, DLDevice* d) {
(void)p; d->device_type = kDLCPU; d->device_id = 0; return MTS_SUCCESS;
}
static mts_status_t fill_dtype(const void* p, DLDataType* dt) {
(void)p; dt->code = kDLFloat; dt->bits = 64; dt->lanes = 1; return MTS_SUCCESS;
}

static int64_t FILL_DL_SHAPE = 1;

static mts_status_t fill_as_dlpack(void* p, DLManagedTensorVersioned** out, DLDevice dev, const int64_t* stream, DLPackVersion ver) {
(void)stream; (void)ver;
DLManagedTensorVersioned* m = (DLManagedTensorVersioned*)calloc(1, sizeof(DLManagedTensorVersioned));
m->version.major = DLPACK_MAJOR_VERSION;
m->version.minor = DLPACK_MINOR_VERSION;
m->dl_tensor.data = p;
m->dl_tensor.device.device_type = kDLCPU;
m->dl_tensor.device.device_id = 0;
m->dl_tensor.ndim = 1;
m->dl_tensor.shape = &FILL_DL_SHAPE;
m->dl_tensor.strides = NULL;
m->dl_tensor.byte_offset = 0;
m->dl_tensor.dtype.code = kDLFloat;
m->dl_tensor.dtype.bits = 64;
m->dl_tensor.dtype.lanes = 1;
m->deleter = (void(*)(DLManagedTensorVersioned*))free;
*out = m;
return MTS_SUCCESS;
}

static mts_array_t scalar_fill_value(void) {
mts_array_t array;
memset(&array, 0, sizeof(array));
array.ptr = &SCALAR_FILL_DATA;
array.shape = fill_shape;
array.origin = fill_origin;
array.device = fill_device;
array.dtype = fill_dtype;
array.as_dlpack = fill_as_dlpack;
return array;
}

// Empty i32 array with shape [0, size] for creating empty labels
static uintptr_t EMPTY_LABELS_SHAPE[2] = {0, 0};

static mts_status_t empty_labels_shape(const void* p, const uintptr_t** shape, uintptr_t* count) {
(void)p; *shape = EMPTY_LABELS_SHAPE; *count = 2; return MTS_SUCCESS;
}
static mts_status_t empty_labels_origin(const void* p, mts_data_origin_t* o) {
(void)p; mts_register_data_origin("c-empty-labels", o); return MTS_SUCCESS;
}
static mts_status_t empty_labels_device(const void* p, DLDevice* d) {
(void)p; d->device_type = kDLCPU; d->device_id = 0; return MTS_SUCCESS;
}
static mts_status_t empty_labels_dtype(const void* p, DLDataType* dt) {
(void)p; dt->code = kDLInt; dt->bits = 32; dt->lanes = 1; return MTS_SUCCESS;
}

static mts_array_t empty_labels_array(size_t n_dimensions) {
mts_array_t array;
memset(&array, 0, sizeof(array));
EMPTY_LABELS_SHAPE[0] = 0;
EMPTY_LABELS_SHAPE[1] = n_dimensions;
array.shape = empty_labels_shape;
array.origin = empty_labels_origin;
array.device = empty_labels_device;
array.dtype = empty_labels_dtype;
return array;
}

static mts_tensormap_t* move_keys_to_samples(mts_tensormap_t* descriptor, const char* keys_to_move[], size_t keys_to_move_len);
static mts_tensormap_t* move_keys_to_properties(mts_tensormap_t* descriptor, const char* keys_to_move[], size_t keys_to_move_len);

Expand Down Expand Up @@ -111,16 +192,21 @@ int main(int argc, char* argv[]) {
goto cleanup;
}

status = array.data(array.ptr, &values);
if (status != MTS_SUCCESS) {
printf("Error: %s\n", mts_last_error());
goto cleanup;
{
DLManagedTensorVersioned* dl_managed = NULL;
DLDevice cpu_device = {kDLCPU, 0};
DLPackVersion max_ver = {DLPACK_MAJOR_VERSION, DLPACK_MINOR_VERSION};
status = array.as_dlpack(array.ptr, &dl_managed, cpu_device, NULL, max_ver);
if (status != MTS_SUCCESS) {
printf("Error: %s\n", mts_last_error());
goto cleanup;
}
values = (double*)dl_managed->dl_tensor.data;
if (dl_managed->deleter) {
dl_managed->deleter(dl_managed);
}
}

if (status != MTS_SUCCESS) {
printf("Error: %s\n", mts_last_error());
goto cleanup;
}
assert(shape_count == 2);

// you can now use `values` as the input of a machine learning algorithm
Expand All @@ -142,31 +228,43 @@ int main(int argc, char* argv[]) {


mts_tensormap_t* move_keys_to_samples(mts_tensormap_t* descriptor, const char* keys_to_move[], size_t keys_to_move_len) {
mts_labels_t keys = {0};
mts_tensormap_t* moved_descriptor = NULL;

keys.names = keys_to_move;
keys.size = keys_to_move_len;
keys.values = NULL;
keys.count = 0;
// Create empty labels with the given dimension names and an empty array
mts_array_t empty_values = empty_labels_array(keys_to_move_len);
mts_labels_t* keys = mts_labels_create(keys_to_move, keys_to_move_len, empty_values);
if (keys == NULL) {
printf("Error creating labels: %s\n", mts_last_error());
mts_tensormap_free(descriptor);
return NULL;
}

moved_descriptor = mts_tensormap_keys_to_samples(descriptor, keys, true);
// Create an empty fill_value array (not used when all blocks have same properties)
mts_array_t fill_value = scalar_fill_value();
moved_descriptor = mts_tensormap_keys_to_samples(descriptor, keys, fill_value, true);
mts_labels_free(keys);
mts_tensormap_free(descriptor);

return moved_descriptor;
}


mts_tensormap_t* move_keys_to_properties(mts_tensormap_t* descriptor, const char* keys_to_move[], size_t keys_to_move_len) {
mts_labels_t keys = {0};
mts_tensormap_t* moved_descriptor = NULL;

keys.names = keys_to_move;
keys.size = keys_to_move_len;
keys.values = NULL;
keys.count = 0;
// Create empty labels with the given dimension names and an empty array
mts_array_t empty_values = empty_labels_array(keys_to_move_len);
mts_labels_t* keys = mts_labels_create(keys_to_move, keys_to_move_len, empty_values);
if (keys == NULL) {
printf("Error creating labels: %s\n", mts_last_error());
mts_tensormap_free(descriptor);
return NULL;
}

moved_descriptor = mts_tensormap_keys_to_properties(descriptor, keys, true);
// Create an empty fill_value array (not used when all blocks have same properties)
mts_array_t fill_value = scalar_fill_value();
moved_descriptor = mts_tensormap_keys_to_properties(descriptor, keys, fill_value, true);
mts_labels_free(keys);
mts_tensormap_free(descriptor);

return moved_descriptor;
Expand Down
2 changes: 1 addition & 1 deletion featomic/examples/compute-soap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {

// descriptor now contains a single block, which can be used as the input
// to standard ML algorithms
let values = descriptor.block_by_id(0).values().to_array();
let values = descriptor.block_by_id(0).values().to_ndarray();
println!("SOAP representation shape: {:?}", values.shape());

Ok(())
Expand Down
Loading
Loading