added new graph metrics

This commit is contained in:
Florian Förster
2024-12-19 16:26:01 +01:00
parent 123869e203
commit 80a35c4658
24 changed files with 826 additions and 97 deletions

View File

@@ -2,7 +2,12 @@ import networkx as nx
import pytest
from lang_main.analysis import graphs
from lang_main.errors import EmptyEdgesError, EmptyGraphError, EdgePropertyNotContainedError
from lang_main.errors import (
EdgePropertyNotContainedError,
EmptyEdgesError,
EmptyGraphError,
NodePropertyNotContainedError,
)
TK_GRAPH_NAME = 'TEST_TOKEN_GRAPH'
@@ -231,6 +236,49 @@ def test_add_weighted_degree():
assert graph_obj.nodes[3][property_name] == 6
def test_add_betweenness_centrality():
graph_obj = build_init_graph(token_graph=False)
property_name = 'betweenness_centrality'
graphs.add_betweenness_centrality(graph_obj, property_name=property_name)
assert round(graph_obj.nodes[1][property_name], 4) == pytest.approx(0.1667)
assert graph_obj.nodes[2][property_name] == 0
assert graph_obj.nodes[3][property_name] == 0
def test_add_importance_metric():
graph_obj = build_init_graph(token_graph=False)
property_name_WD = 'degree_weighted'
graphs.add_weighted_degree(graph_obj, 'weight', property_name_WD)
property_name_BC = 'betweenness_centrality'
graphs.add_betweenness_centrality(graph_obj, property_name=property_name_BC)
property_name = 'importance'
graphs.add_importance_metric(
graph_obj,
property_name=property_name,
property_name_weighted_degree=property_name_WD,
property_name_betweenness=property_name_BC,
)
assert round(graph_obj.nodes[1][property_name], 4) == pytest.approx(2.3333)
assert graph_obj.nodes[2][property_name] == 0
assert graph_obj.nodes[3][property_name] == 0
with pytest.raises(NodePropertyNotContainedError):
graphs.add_importance_metric(
graph_obj,
property_name=property_name,
property_name_weighted_degree='prop_not_contained',
property_name_betweenness=property_name_BC,
)
with pytest.raises(NodePropertyNotContainedError):
graphs.add_importance_metric(
graph_obj,
property_name=property_name,
property_name_weighted_degree=property_name_WD,
property_name_betweenness='prop_not_contained',
)
def test_static_graph_analysis():
graph_obj = build_init_graph(token_graph=True)
(graph_obj,) = graphs.static_graph_analysis(graph_obj) # type: ignore
@@ -254,6 +302,20 @@ def test_pipe_add_graph_metrics():
assert graph_collection[1].nodes[1][property_name] == 14
assert graph_collection[1].nodes[2][property_name] == 10
assert graph_collection[1].nodes[3][property_name] == 6
property_name = 'betweenness_centrality'
assert round(graph_collection[0].nodes[1][property_name], 4) == pytest.approx(0.1667)
assert graph_collection[0].nodes[2][property_name] == 0
assert graph_collection[0].nodes[3][property_name] == 0
assert round(graph_collection[1].nodes[1][property_name], 4) == pytest.approx(0.1667)
assert graph_collection[1].nodes[2][property_name] == 0
assert graph_collection[1].nodes[3][property_name] == 0
property_name = 'importance'
assert round(graph_collection[0].nodes[1][property_name], 4) == pytest.approx(2.3333)
assert graph_collection[0].nodes[2][property_name] == 0
assert graph_collection[0].nodes[3][property_name] == 0
assert round(graph_collection[1].nodes[1][property_name], 4) == pytest.approx(2.3333)
assert graph_collection[1].nodes[2][property_name] == 0
assert graph_collection[1].nodes[3][property_name] == 0
def test_pipe_rescale_graph_edge_weights(tk_graph):

View File

@@ -121,6 +121,7 @@ def test_pipeline_valid(pipeline, alter_content):
assert len(pipe.actions) == 1
assert len(pipe.action_names) == 1
assert len(pipe.actions_kwargs) == 1
assert len(pipe.action_skip) == 1
assert len(pipe.save_results) == 1
assert len(pipe.load_results) == 1
assert pipe.save_results[0] == (False, None)
@@ -166,7 +167,7 @@ def test_pipeline_valid_action_load(pipeline, working_dir):
test_string = 'test'
# action preparation
def valid_action(string, add_content=False):
def valid_action(string, add_content=False): # pragma: no cover
if add_content:
string += '_2'
return string
@@ -175,6 +176,7 @@ def test_pipeline_valid_action_load(pipeline, working_dir):
assert len(pipe.actions) == 1
assert len(pipe.action_names) == 1
assert len(pipe.actions_kwargs) == 1
assert len(pipe.action_skip) == 1
assert len(pipe.save_results) == 1
assert len(pipe.load_results) == 1
assert pipe.save_results[0] == (False, None)
@@ -209,19 +211,28 @@ def test_pipeline_multiple_actions(pipeline):
string += '_3'
return string
pipe.add(valid_action, {'add_content': True}, skip=True)
pipe.add(valid_action, {'add_content': True})
pipe.add(valid_action_2)
assert len(pipe.actions) == 2
assert len(pipe.action_names) == 2
assert len(pipe.actions_kwargs) == 2
assert len(pipe.save_results) == 2
assert len(pipe.load_results) == 2
assert len(pipe.actions) == 3
assert len(pipe.action_names) == 3
assert len(pipe.actions_kwargs) == 3
assert len(pipe.action_skip) == 3
assert len(pipe.save_results) == 3
assert len(pipe.load_results) == 3
assert pipe.save_results[1] == (False, None)
assert pipe.load_results[1] == (False, None)
ret = pipe.run(starting_values=(test_string,))
assert isinstance(ret, tuple)
assert pipe._intermediate_result == ret
assert pipe.curr_proc_idx == 3
assert pipe.curr_proc_idx == 4
assert ret is not None
assert ret[0] == 'test_2_3'
def test_pipeline_invalid_action(pipeline):
test_string = 'test'
with pytest.raises(WrongActionTypeError):
pipeline.add(test_string, skip=False)

View File

@@ -0,0 +1,54 @@
import builtins
import importlib.util
from importlib import reload
import pytest
from lang_main.errors import DependencyMissingError
@pytest.fixture(scope='function')
def no_dep(monkeypatch):
import_orig = builtins.__import__
def mocked_import(name, globals, locals, fromlist, level):
if name == 'py4cytoscape':
raise ImportError()
return import_orig(name, locals, fromlist, level)
monkeypatch.setattr(builtins, '__import__', mocked_import)
@pytest.fixture(scope='function')
def patch_find_spec(monkeypatch):
find_spec_orig = importlib.util.find_spec
def mocked_find_spec(*args, **kwargs):
if args[0] == 'py4cytoscape':
return None
else:
return find_spec_orig(*args, **kwargs)
monkeypatch.setattr(importlib.util, 'find_spec', mocked_find_spec)
def test_p4c_available():
import lang_main.constants
reload(lang_main.constants)
assert lang_main.constants.Dependencies.PY4C.value
@pytest.mark.usefixtures('patch_find_spec')
def test_p4c_missing(monkeypatch):
import lang_main.constants
reload(lang_main.constants)
assert not lang_main.constants.Dependencies.PY4C.value
with pytest.raises(DependencyMissingError):
from lang_main import render
reload(render)

View File

@@ -16,7 +16,7 @@ def test_p4c_dependency():
def test_load_config():
toml_path = config.PKG_DIR / 'lang_main_config.toml'
loaded_cfg = config.load_toml_config(toml_path)
assert loaded_cfg['info']['pkg'] == 'lang_main_internal'
assert loaded_cfg['paths']['models'] == './lang-models'
def test_get_config_path():
@@ -36,7 +36,7 @@ def test_get_config_path():
assert cyto_internal == cyto_cfg_pth
def test_load_cfg(monkeypatch, tmp_path):
def test_load_cfg_func(monkeypatch, tmp_path):
monkeypatch.setattr(Path, 'cwd', lambda: tmp_path)
pkg_dir = config.PKG_DIR
filename = config.CONFIG_FILENAME
@@ -44,21 +44,20 @@ def test_load_cfg(monkeypatch, tmp_path):
cfg_pth_internal = (pkg_dir / filename).resolve()
ref_config = config.load_toml_config(cfg_pth_internal)
assert ref_config['paths']['models'] == './lang-models'
assert ref_config['info']['pkg'] == 'lang_main_internal'
loaded_cfg = config.load_cfg(
starting_path=pkg_dir,
glob_pattern=filename,
stop_folder_name=stop_folder,
cfg_path_internal=cfg_pth_internal,
prefer_internal_config=True,
lookup_cwd=False,
)
assert loaded_cfg['info']['pkg'] == 'lang_main_internal'
assert loaded_cfg['paths']['models'] == '../lang-models'
loaded_cfg = config.load_cfg(
starting_path=pkg_dir,
glob_pattern=filename,
stop_folder_name=stop_folder,
cfg_path_internal=cfg_pth_internal,
prefer_internal_config=False,
lookup_cwd=True,
)
assert loaded_cfg['info']['pkg'] == 'lang_main'
assert loaded_cfg['paths']['models'] == '../lang-models'

View File

@@ -4,12 +4,12 @@ from spacy.language import Language
from lang_main import model_loader
from lang_main.constants import (
STFR_MODEL_ARGS_ONNX,
SimilarityFunction,
SpacyModelTypes,
STFRBackends,
STFRDeviceTypes,
STFRModelTypes,
stfr_model_args_onnx,
)
from lang_main.errors import LanguageModelNotFoundError
from lang_main.types import LanguageModels
@@ -69,7 +69,7 @@ def test_load_sentence_transformer_onnx(model_name, similarity_func) -> None:
similarity_func=similarity_func,
backend=STFRBackends.ONNX,
device=STFRDeviceTypes.CPU,
model_kwargs=STFR_MODEL_ARGS_ONNX, # type: ignore
model_kwargs=stfr_model_args_onnx, # type: ignore
)
assert isinstance(model, SentenceTransformer)

Binary file not shown.