Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
D
dccQuantities
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
DigitalDynamicMeasurement
dccQuantities
Commits
b39c1877
Commit
b39c1877
authored
3 months ago
by
Benedikt
Browse files
Options
Downloads
Patches
Plain Diff
added first try of indexing helper functions
parent
1ee5f98c
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/helpers.py
+102
-11
102 additions, 11 deletions
src/helpers.py
tests/test_helpers.py
+103
-1
103 additions, 1 deletion
tests/test_helpers.py
with
205 additions
and
12 deletions
src/helpers.py
+
102
−
11
View file @
b39c1877
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.
"""
...
...
This diff is collapsed.
Click to expand it.
tests/test_helpers.py
+
103
−
1
View file @
b39c1877
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
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment