Skip to content
Snippets Groups Projects
Commit b39c1877 authored by Benedikt's avatar Benedikt
Browse files

added first try of indexing helper functions

parent 1ee5f98c
Branches
No related tags found
No related merge requests found
from __future__ import annotations
from typing import TYPE_CHECKING
import warnings
import operator
import numpy as np
from typing import Union
from metas_unclib import ufloat
import re
import json
from dsiUnits import dsiUnit
import warnings
from enum import Enum
import locale
import sys
if TYPE_CHECKING:
# This import is only for type-checking purposes and won't be executed at runtime.
......@@ -279,10 +282,6 @@ def assert_dicts_equal(dict1, dict2):
assert not removed, f"Removed keys: {removed}"
assert not modified, f"Modified keys: {modified}"
import numpy as np
def dict_compare(d1, d2):
d1_keys = set(d1.keys())
d2_keys = set(d2.keys())
......@@ -331,15 +330,107 @@ def dict_compare(d1, d2):
return added, removed, modified, same
get_valsFromUFloatArrays = np.vectorize(lambda x: x.value)
get_uncerFromUFloatArrays = np.vectorize(lambda x: x.stdunc)
# --- Functions Under Test ---
import pycountry
import locale
import sys
def get_exact_slice(index_vector, query):
"""
For a given 1D index vector and one or more query float values,
returns a slice covering all indices that exactly match.
"""
arr = np.array(index_vector)
if not isinstance(query, (list, np.ndarray)):
query = [query]
matching_indices = []
for q in query:
idx = np.where(arr == q)[0]
if idx.size == 0:
raise ValueError(f"No match found for query {q}.")
matching_indices.append(idx)
matching_indices = np.unique(np.concatenate(matching_indices))
if matching_indices.size > 1:
warnings.warn("Multiple matching indices found; returning slice covering all matches.")
start = int(matching_indices.min())
stop = int(matching_indices.max()) + 1
return slice(start, stop)
def get_conditional_slice(index_vector, condition):
"""
Given a 1D index vector and a condition tuple (operator, value),
returns a slice covering all indices that satisfy the condition.
"""
arr = np.array(index_vector)
op_str, q = condition
ops = {
'==': operator.eq,
'<': operator.lt,
'<=': operator.le,
'>': operator.gt,
'>=': operator.ge,
'!=': operator.ne
}
if op_str not in ops:
raise ValueError("Unsupported operator: " + op_str)
op_func = ops[op_str]
mask = op_func(arr, q)
matching_indices = np.where(mask)[0]
if matching_indices.size == 0:
raise ValueError(f"No indices satisfy condition {op_str} {q}.")
if matching_indices.size > 1:
warnings.warn("Multiple matching indices found; returning slice covering all matches.")
start = int(matching_indices.min())
stop = int(matching_indices.max()) + 1
return slice(start, stop)
def get_nearest_slice(index_vector, query, mode='absolute'):
"""
Given a 1D index vector and a query float value, returns a slice covering
the nearest index (or indices) based on the specified mode.
Modes:
- 'lower': nearest index with value <= query.
- 'higher': nearest index with value >= query.
- 'absolute': index with smallest absolute difference.
"""
arr = np.array(index_vector)
if not isinstance(query, (list, np.ndarray)):
query = [query]
all_indices = []
for q in query:
# If an exact match exists, use it immediately.
exact_idx = np.where(arr == q)[0]
if exact_idx.size > 0:
all_indices.append(int(exact_idx[0]))
continue
if mode == 'lower':
candidates = np.where(arr <= q)[0]
if candidates.size == 0:
raise ValueError(f"No index found lower than or equal to {q}.")
all_indices.append(int(candidates.max()))
elif mode == 'higher':
candidates = np.where(arr >= q)[0]
if candidates.size == 0:
raise ValueError(f"No index found higher than or equal to {q}.")
all_indices.append(int(candidates.min()))
elif mode == 'absolute':
diffs = np.abs(arr - q)
min_diff = diffs.min()
nearest = np.where(diffs == min_diff)[0]
if nearest.size > 1:
warnings.warn(f"Multiple indices equally near {q}; returning slice covering them.")
all_indices.extend(nearest)
else:
all_indices.append(int(nearest[0]))
else:
raise ValueError(f"Unsupported mode: {mode}")
all_indices = np.unique(all_indices)
start = int(all_indices.min())
stop = int(all_indices.max()) + 1
return slice(start, stop)
get_valsFromUFloatArrays = np.vectorize(lambda x: x.value)
get_uncerFromUFloatArrays = np.vectorize(lambda x: x.stdunc)
def get_system_language() -> str:
"""Detects the system language for Windows, Linux, and macOS."""
......
from helpers import *
import numpy as np
import pytest
import warnings
import operator
def test_isListOfTypes():
assert isListOfTypes([1, 2, 3], [int])
assert not isListOfTypes([1, 2, 3.0], [int])
assert isListOfTypes([1, 2, 3.3], [int, float])
assert isListOfTypes(np.array([1, 2, 3]), [np.integer])
\ No newline at end of file
assert isListOfTypes(np.array([1, 2, 3]), [np.integer])
def test_get_exact_slice_single():
index_vector = [0.0, 0.5, 1.0, 1.5, 2.0]
s = get_exact_slice(index_vector, 1.0)
# 1.0 is at index 2 → expected slice(2, 3)
assert s.start == 2 and s.stop == 3
def test_get_exact_slice_multiple_matches():
index_vector = np.array([1.0, 1.0, 2.0, 3.0])
with pytest.warns(UserWarning, match="Multiple matching indices found"):
s = get_exact_slice(index_vector, 1.0)
# Expected unique indices: [0, 1] → slice(0, 2)
assert s.start == 0 and s.stop == 2
def test_get_exact_slice_no_match():
index_vector = np.array([0.0, 0.5, 1.0, 1.5, 2.0])
with pytest.raises(ValueError, match="No match found for query"):
get_exact_slice(index_vector, 3.0)
def test_get_exact_slice_list_query():
index_vector = [0.0, 0.5, 1.0, 1.5, 2.0]
# Querying two values: 0.5 and 1.5 → expected unique indices: [1, 3] → slice(1, 4)
s = get_exact_slice(index_vector, [0.5, 1.5])
assert s.start == 1 and s.stop == 4
# Tests for get_conditional_slice
def test_get_conditional_slice_le():
index_vector = [0.0, 0.5, 1.0, 1.5, 2.0]
# Condition ('<=', 1.0) → indices [0,1,2] → slice(0,3)
s = get_conditional_slice(index_vector, ('<=', 1.0))
assert s.start == 0 and s.stop == 3
def test_get_conditional_slice_gt():
index_vector = [0.0, 0.5, 1.0, 1.5, 2.0]
# Condition ('>', 1.0) → indices [3,4] → slice(3,5)
s = get_conditional_slice(index_vector, ('>', 1.0))
assert s.start == 3 and s.stop == 5
def test_get_conditional_slice_equal():
index_vector = [0.0, 0.5, 1.0, 1.5, 2.0]
s = get_conditional_slice(index_vector, ('==', 1.5))
assert s.start == 3 and s.stop == 4
def test_get_conditional_slice_no_match():
index_vector = [0.0, 0.5, 1.0, 1.5, 2.0]
with pytest.raises(ValueError, match="No indices satisfy condition"):
get_conditional_slice(index_vector, ('<', -1.0))
def test_get_conditional_slice_unsupported_operator():
index_vector = [0.0, 0.5, 1.0, 1.5, 2.0]
with pytest.raises(ValueError, match="Unsupported operator"):
get_conditional_slice(index_vector, ('**', 1.0))
# Tests for get_nearest_slice
def test_get_nearest_slice_exact_match():
index_vector = [0.0, 0.5, 1.0, 1.5, 2.0]
# Query 1.5 exists exactly (index 3)
s = get_nearest_slice(index_vector, 1.5, mode='absolute')
assert s.start == 3 and s.stop == 4
def test_get_nearest_slice_lower():
index_vector = [0.0, 0.5, 1.0, 1.5, 2.0]
# Query 1.2, mode 'lower' → candidates: indices [0,1,2] → max is index 2
s = get_nearest_slice(index_vector, 1.2, mode='lower')
assert s.start == 2 and s.stop == 3
def test_get_nearest_slice_higher():
index_vector = [0.0, 0.5, 1.0, 1.5, 2.0]
# Query 1.2, mode 'higher' → candidates: indices [3,4] → min is index 3
s = get_nearest_slice(index_vector, 1.2, mode='higher')
assert s.start == 3 and s.stop == 4
def test_get_nearest_slice_absolute():
index_vector = [0.0, 0.5, 1.0, 1.5, 2.0]
# Query 1.2, mode 'absolute' → diff: [1.2,0.7,0.2,0.3,0.8] → closest index is 2
s = get_nearest_slice(index_vector, 1.2, mode='absolute')
assert s.start == 2 and s.stop == 3
def test_get_nearest_slice_tie():
# Create a tie: index_vector with two equally near values.
index_vector = [1.0, 1.5, 2.0]
# Query 1.75 → diffs: [0.75, 0.25, 0.25] → tie between indices 1 and 2.
with pytest.warns(UserWarning, match="Multiple indices equally near"):
s = get_nearest_slice(index_vector, 1.75, mode='absolute')
# Expected unique indices: [1,2] → slice(1, 3)
assert s.start == 1 and s.stop == 3
def test_get_nearest_slice_no_lower():
index_vector = [1.0, 1.5, 2.0]
with pytest.raises(ValueError, match="No index found lower than or equal to"):
get_nearest_slice(index_vector, 0.5, mode='lower')
def test_get_nearest_slice_no_higher():
index_vector = [1.0, 1.5, 2.0]
with pytest.raises(ValueError, match="No index found higher than or equal to"):
get_nearest_slice(index_vector, 2.5, mode='higher')
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment