From e664ba602abe0f304a90e44bb7b61e22cc322a61 Mon Sep 17 00:00:00 2001 From: Chris Chamberlain Date: Thu, 6 Jun 2024 17:05:48 +1200 Subject: [PATCH 1/3] new gmm classes & tests; WIP util LIB is updated; --- .../schema/nshm_model_gmms_schema.py | 139 ++++++++++++ .../schema/nshm_model_schema.py | 11 +- tests/test_schema_gmm_models_as_relay_node.py | 139 ++++++++++++ tests/test_schema_model_gmm_logic_tree.py | 94 ++++++++ tests/test_schema_models_as_relay_node.py | 203 ----------------- ...test_schema_source_models_as_relay_node.py | 213 ++++++++++++++++++ 6 files changed, 593 insertions(+), 206 deletions(-) create mode 100644 nshm_model_graphql_api/schema/nshm_model_gmms_schema.py create mode 100644 tests/test_schema_gmm_models_as_relay_node.py create mode 100644 tests/test_schema_model_gmm_logic_tree.py create mode 100644 tests/test_schema_source_models_as_relay_node.py diff --git a/nshm_model_graphql_api/schema/nshm_model_gmms_schema.py b/nshm_model_graphql_api/schema/nshm_model_gmms_schema.py new file mode 100644 index 0000000..e16299c --- /dev/null +++ b/nshm_model_graphql_api/schema/nshm_model_gmms_schema.py @@ -0,0 +1,139 @@ +"""Define graphene model for nzshm_model gmm logic tree classes.""" + +import logging +from functools import lru_cache + +import graphene +from graphene import relay + +from .nshm_model_sources_schema import get_model_by_version + +log = logging.getLogger(__name__) + + +# TODO: this method belongs on the nzshm-model gmcm class +@lru_cache +def get_branch_set(model_version, tectonic_region_type): + glt = get_model_by_version(model_version).gmm_logic_tree + log.debug(f"glt {glt}") + for bs in glt.branch_sets: + if bs.tectonic_region_type == tectonic_region_type: + return bs + assert 0, f"branch set {tectonic_region_type} was not found" # pragma: no cover + + +# TODO: this method belongs on the nzshm-model gmcm class +@lru_cache +def get_logic_tree_branch(model_version, branch_set_trt, gsim_name, gsim_args): + log.info( + f"get_logic_tree_branch: {branch_set_trt} gsim_name: {gsim_name} gsim_args: {gsim_args}" + ) + branch_set = get_branch_set(model_version, branch_set_trt) + for ltb in branch_set.branches: + if (ltb.gsim_name == gsim_name) and (str(ltb.gsim_args) == gsim_args): + return ltb + print(branch_set_trt, ltb.tag) + assert ( + 0 + ), f"branch with gsim_name: {gsim_name} gsim_args: {gsim_args} was not found" # pragma: no cover + + +class GmmLogicTreeBranch(graphene.ObjectType): + class Meta: + interfaces = (relay.Node,) + + model_version = graphene.String() + branch_set_trt = graphene.String() + gsim_name = graphene.String() + gsim_args = graphene.String() + tectonic_region_type = graphene.String() # should be an enum + weight = graphene.Float() + + def resolve_id(self, info): + return f"{self.model_version}:{self.branch_set_trt}:{self.gsim_name}:{self.gsim_args}" + + @classmethod + def get_node(cls, info, node_id: str): + model_version, branch_set_trt, gsim_name, gsim_args = node_id.split(":") + gltb = get_logic_tree_branch( + model_version, branch_set_trt, gsim_name, gsim_args + ) + return GmmLogicTreeBranch( + model_version=model_version, + branch_set_trt=branch_set_trt, + gsim_name=gsim_name, + gsim_args=gsim_args, + weight=gltb.weight, + ) + + +class GmmBranchSet(graphene.ObjectType): + """Ground Motion Model branch sets, + + to ensure that the wieghts of the enclosed branches sum to 1.0 + """ + + class Meta: + interfaces = (relay.Node,) + + model_version = graphene.String() + short_name = graphene.String() + long_name = graphene.String() + tectonic_region_type = graphene.String() + branches = graphene.List(GmmLogicTreeBranch) + + def resolve_id(self, info): + return f"{self.model_version}:{self.tectonic_region_type}" + + @classmethod + def get_node(cls, info, node_id: str): + model_version, tectonic_region_type = node_id.split(":") + bs = get_branch_set(model_version, tectonic_region_type) + return GmmBranchSet( + model_version=model_version, + tectonic_region_type=tectonic_region_type, + short_name=bs.short_name, + long_name=bs.long_name, + ) + + @staticmethod + def resolve_branches(root, info, **kwargs): + log.info(f"resolve_branches root: {root} kwargs: {kwargs}") + bs = get_branch_set(root.model_version, root.tectonic_region_type) + for ltb in bs.branches: + log.debug(ltb) + ltb = GmmLogicTreeBranch( + model_version=root.model_version, + tectonic_region_type=root.tectonic_region_type, + weight=ltb.weight, + gsim_name=ltb.gsim_name, + gsim_args=str(ltb.gsim_args), + ) + yield ltb + + +class GroundMotionModelLogicTree(graphene.ObjectType): + """A custom Node representing the GMM logic tree of a given model.""" + + class Meta: + interfaces = (relay.Node,) + + model_version = graphene.String() + branch_sets = graphene.List(GmmBranchSet) + + def resolve_id(self, info): + return self.model_version + + @classmethod + def get_node(cls, info, model_version: str): + return GroundMotionModelLogicTree(model_version=model_version) + + @staticmethod + def resolve_branch_sets(root, info, **kwargs): + log.info(f"resolve_branch_sets root: {root} kwargs: {kwargs}") + glt = get_model_by_version(root.model_version).gmm_logic_tree + for bs in glt.branch_sets: + yield GmmBranchSet( + model_version=root.model_version, + tectonic_region_type=bs.tectonic_region_type, + ) diff --git a/nshm_model_graphql_api/schema/nshm_model_schema.py b/nshm_model_graphql_api/schema/nshm_model_schema.py index a44bda6..2687b6b 100644 --- a/nshm_model_graphql_api/schema/nshm_model_schema.py +++ b/nshm_model_graphql_api/schema/nshm_model_schema.py @@ -7,6 +7,7 @@ import nzshm_model as nm from graphene import relay +from .nshm_model_gmms_schema import GroundMotionModelLogicTree from .nshm_model_sources_schema import SourceLogicTree log = logging.getLogger(__name__) @@ -21,6 +22,7 @@ class Meta: version = graphene.String() title = graphene.String() source_logic_tree = graphene.Field(SourceLogicTree) + gmm_logic_tree = graphene.Field(GroundMotionModelLogicTree) def resolve_id(self, info): return self.version @@ -28,9 +30,12 @@ def resolve_id(self, info): @staticmethod def resolve_source_logic_tree(root, info, **kwargs): log.info(f"resolve_source_logic_tree root: {root} kwargs: {kwargs}") - return SourceLogicTree( - model_version=root.version - ) # , branch_sets=get_branch_sets(slt)) + return SourceLogicTree(model_version=root.version) + + @staticmethod + def resolve_gmm_logic_tree(root, info, **kwargs): + log.info(f"resolve_gmm_logic_tree root: {root} kwargs: {kwargs}") + return GroundMotionModelLogicTree(model_version=root.version) @classmethod def get_node(cls, info, version: str): diff --git a/tests/test_schema_gmm_models_as_relay_node.py b/tests/test_schema_gmm_models_as_relay_node.py new file mode 100644 index 0000000..f65831d --- /dev/null +++ b/tests/test_schema_gmm_models_as_relay_node.py @@ -0,0 +1,139 @@ +import pytest +from graphene.test import Client +from graphql_relay import to_global_id + +from nshm_model_graphql_api import schema + + +@pytest.fixture(scope="module") +def client(): + return Client(schema.schema_root) + + +@pytest.mark.parametrize( + "model_version", + ["NSHM_v1.0.0", "NSHM_v1.0.4"], +) +def test_get_model_SourceLogicTree_as_node(client, model_version): + QUERY = """ + query { + node(id: "%s") + { + ... on Node { + id + } + ... on GroundMotionModelLogicTree { + model_version + } + } + } + """ % to_global_id( + "GroundMotionModelLogicTree", model_version + ) + print(QUERY) + executed = client.execute(QUERY) + print(executed) + assert executed["data"]["node"]["model_version"] == model_version + assert executed["data"]["node"]["id"] == to_global_id( + "GroundMotionModelLogicTree", model_version + ) + + +@pytest.mark.parametrize( + "model_version, short_name, long_name", + [ + ("NSHM_v1.0.0", "Active Shallow Crust", "Crustal"), + # ("NSHM_v1.0.0", "PUY", "Puysegur"), + # ("NSHM_v1.0.4", "CRU", "Crustal"), + # ("NSHM_v1.0.4", "PUY", "Puysegur"), + ], +) +def test_get_model_GmmBranchSet_as_node(client, model_version, short_name, long_name): + QUERY = """ + query { + node(id: "%s") + { + ... on Node { + id + } + ... on GmmBranchSet { + model_version + short_name + long_name + tectonic_region_type + } + + } + } + """ % to_global_id( + "GmmBranchSet", f"{model_version}:{short_name}" + ) + executed = client.execute(QUERY) + print(executed) + assert executed["data"]["node"]["model_version"] == model_version + assert executed["data"]["node"]["tectonic_region_type"] == short_name + # assert executed["data"]["node"]["long_name"] == long_name + assert executed["data"]["node"]["id"] == to_global_id( + "GmmBranchSet", f"{model_version}:{short_name}" + ) + + +''' + +@pytest.mark.parametrize( + "model_version, branch_set_short_name, tag, weight", + [ + ( + "NSHM_v1.0.0", + "CRU", + "[dmgeologic, tdFalse, bN[1.089, 4.6], C4.2, s1.0]", + 0.00541000379473566, + ), + ("NSHM_v1.0.0", "PUY", "[dm0.7, bN[0.902, 4.6], C4.0, s0.28]", 0.21), + ( + "NSHM_v1.0.4", + "CRU", + "[dmgeologic, tdFalse, bN[1.089, 4.6], C4.2, s1.41]", + 0.00286782725429677, + ), + ("NSHM_v1.0.4", "PUY", "[dm0.7, bN[0.902, 4.6], C4.0, s0.28]", 0.21), + ], +) +def test_get_model_SourceLogicTreeBranch_as_node( + client, model_version, branch_set_short_name, tag, weight +): + QUERY = """ + query { + node(id: "%s") + { + ... on Node { + id + } + ... on SourceLogicTreeBranch { + model_version + branch_set_short_name + tag + weight + sources { + ... on BranchInversionSource { + nrml_id + } + } + } + + } + } + """ % to_global_id( + "SourceLogicTreeBranch", f"{model_version}:{branch_set_short_name}:{tag}" + ) + executed = client.execute(QUERY) + print(executed) + assert executed["data"]["node"]["id"] == to_global_id( + "SourceLogicTreeBranch", f"{model_version}:{branch_set_short_name}:{tag}" + ) + + assert executed["data"]["node"]["model_version"] == model_version + assert executed["data"]["node"]["branch_set_short_name"] == branch_set_short_name + assert executed["data"]["node"]["tag"] == tag + assert executed["data"]["node"]["weight"] == weight +''' diff --git a/tests/test_schema_model_gmm_logic_tree.py b/tests/test_schema_model_gmm_logic_tree.py new file mode 100644 index 0000000..ad6a860 --- /dev/null +++ b/tests/test_schema_model_gmm_logic_tree.py @@ -0,0 +1,94 @@ +import pytest +from graphene.test import Client + +from nshm_model_graphql_api import schema + +# from graphql_relay import to_global_id + + +@pytest.fixture(scope="module") +def client(): + return Client(schema.schema_root) + + +@pytest.mark.parametrize( + "model_version", + ["NSHM_v1.0.0", "NSHM_v1.0.4"], +) +def test_get_model_and_branch_sets(client, model_version): + QUERY = ( + """ + query { + get_model(version: "%s") + { + gmm_logic_tree { + branch_sets { + __typename + model_version + # short_name + # long_name + tectonic_region_type + } + } + ... on Node { + id + } + } + } + """ + % model_version + ) + executed = client.execute(QUERY) + print(executed) + branch_sets = executed["data"]["get_model"]["gmm_logic_tree"]["branch_sets"] + assert branch_sets[0]["__typename"] == "GmmBranchSet" + assert branch_sets[0]["model_version"] == model_version + assert branch_sets[0]["tectonic_region_type"] == "Active Shallow Crust" + # assert branch_sets[0]["short_name"] == "PUY" + + +@pytest.mark.parametrize( + "model_version", + [ + "NSHM_v1.0.4", + "NSHM_v1.0.0", + ], +) +def test_get_model_and_branch_set_branches(client, model_version): + QUERY = ( + """ + query { + get_model(version: "%s") + { + gmm_logic_tree { + branch_sets { + # short_name + branches { + __typename + # branch_set_short_name + model_version + weight + gsim_name + gsim_args + } + } + } + ... on Node { + id + } + } + } + """ + % model_version + ) + executed = client.execute(QUERY) + print(executed) + branch_sets = executed["data"]["get_model"]["gmm_logic_tree"]["branch_sets"] + # assert branch_sets[0]["short_name"] == "PUY" + assert branch_sets[0]["branches"][0]["weight"] <= 1.0 + assert branch_sets[0]["branches"][0]["gsim_name"] == "Stafford2022" + assert branch_sets[0]["branches"][0]["gsim_args"] == "{'mu_branch': 'Upper'}" + + assert branch_sets[0]["branches"][0]["__typename"] == "GmmLogicTreeBranch" + assert branch_sets[0]["branches"][0]["model_version"] == model_version + # assert branch_sets[0]["branches"][0]["branch_set_short_name"] == "PUY" diff --git a/tests/test_schema_models_as_relay_node.py b/tests/test_schema_models_as_relay_node.py index 581c97f..af07963 100644 --- a/tests/test_schema_models_as_relay_node.py +++ b/tests/test_schema_models_as_relay_node.py @@ -36,206 +36,3 @@ def test_get_model_as_node(client, version): assert executed["data"]["node"]["version"] == version assert executed["data"]["node"]["title"] is not None assert executed["data"]["node"]["id"] == to_global_id("NshmModel", version) - - -@pytest.mark.parametrize( - "model_version", - ["NSHM_v1.0.0", "NSHM_v1.0.4"], -) -def test_get_model_SourceLogicTree_as_node(client, model_version): - QUERY = """ - query { - node(id: "%s") - { - ... on Node { - id - } - ... on SourceLogicTree { - model_version - } - } - } - """ % to_global_id( - "SourceLogicTree", model_version - ) - print(QUERY) - executed = client.execute(QUERY) - print(executed) - assert executed["data"]["node"]["model_version"] == model_version - assert executed["data"]["node"]["id"] == to_global_id( - "SourceLogicTree", model_version - ) - - -@pytest.mark.parametrize( - "model_version, short_name, long_name", - [ - ("NSHM_v1.0.0", "CRU", "Crustal"), - ("NSHM_v1.0.0", "PUY", "Puysegur"), - ("NSHM_v1.0.4", "CRU", "Crustal"), - ("NSHM_v1.0.4", "PUY", "Puysegur"), - ], -) -def test_get_model_SourceBranchSet_as_node( - client, model_version, short_name, long_name -): - QUERY = """ - query { - node(id: "%s") - { - ... on Node { - id - } - ... on SourceBranchSet { - model_version - short_name - long_name - } - - } - } - """ % to_global_id( - "SourceBranchSet", f"{model_version}:{short_name}" - ) - executed = client.execute(QUERY) - print(executed) - assert executed["data"]["node"]["model_version"] == model_version - assert executed["data"]["node"]["short_name"] == short_name - assert executed["data"]["node"]["long_name"] == long_name - assert executed["data"]["node"]["id"] == to_global_id( - "SourceBranchSet", f"{model_version}:{short_name}" - ) - - -@pytest.mark.parametrize( - "model_version, branch_set_short_name, tag, weight", - [ - ( - "NSHM_v1.0.0", - "CRU", - "[dmgeologic, tdFalse, bN[1.089, 4.6], C4.2, s1.0]", - 0.00541000379473566, - ), - ("NSHM_v1.0.0", "PUY", "[dm0.7, bN[0.902, 4.6], C4.0, s0.28]", 0.21), - ( - "NSHM_v1.0.4", - "CRU", - "[dmgeologic, tdFalse, bN[1.089, 4.6], C4.2, s1.41]", - 0.00286782725429677, - ), - ("NSHM_v1.0.4", "PUY", "[dm0.7, bN[0.902, 4.6], C4.0, s0.28]", 0.21), - ], -) -def test_get_model_SourceLogicTreeBranch_as_node( - client, model_version, branch_set_short_name, tag, weight -): - QUERY = """ - query { - node(id: "%s") - { - ... on Node { - id - } - ... on SourceLogicTreeBranch { - model_version - branch_set_short_name - tag - weight - sources { - ... on BranchInversionSource { - nrml_id - } - } - } - - } - } - """ % to_global_id( - "SourceLogicTreeBranch", f"{model_version}:{branch_set_short_name}:{tag}" - ) - executed = client.execute(QUERY) - print(executed) - assert executed["data"]["node"]["id"] == to_global_id( - "SourceLogicTreeBranch", f"{model_version}:{branch_set_short_name}:{tag}" - ) - - assert executed["data"]["node"]["model_version"] == model_version - assert executed["data"]["node"]["branch_set_short_name"] == branch_set_short_name - assert executed["data"]["node"]["tag"] == tag - assert executed["data"]["node"]["weight"] == weight - - -# @pytest.mark.parametrize( -# "model_version, branch_set_short_name, nrml_id, rupture_set_id, error", -# [ -# ( -# "NSHM_v1.0.0", -# "CRU", -# "SW52ZXJzaW9uU29sdXRpb25Ocm1sOjEyMDg5Mg==", -# "RmlsZToxMDAwODc=", -# None, -# ), -# ( -# "NSHM_v1.0.0", -# "PUY", -# "SW52ZXJzaW9uU29sdXRpb25Ocm1sOjExODcxNw==", -# "RmlsZToxNzU3My4wQUYzU1o=", -# None, -# ), -# ( -# "NSHM_v1.0.4", -# "CRU", -# "SW52ZXJzaW9uU29sdXRpb25Ocm1sOjEyOTE0ODY=", -# "RmlsZToxMDAwODc=", -# None, -# ), -# ( -# "NSHM_v1.0.0", -# "CRU", -# "SW52ZXJzaW9uU29sdXRpb25Ocm1sOjEyOTE0ODY=", -# "", -# "`NSHM_v1.0.0:CRU:1291486` was not found", -# ), -# ], -# ) -# def test_get_model_BranchInversionSource_as_node( -# client, model_version, branch_set_short_name, nrml_id, rupture_set_id, error -# ): -# QUERY = """ -# query { -# node(id: "%s") -# { -# ... on Node { -# id -# } -# ... on BranchInversionSource { -# model_version -# branch_set_short_name -# nrml_id -# rupture_set_id -# } - -# } -# } -# """ % to_global_id( -# "BranchInversionSource", -# f"{model_version}:{branch_set_short_name}:{from_global_id(nrml_id)[1]}", -# ) - -# print(QUERY) -# executed = client.execute(QUERY) -# print(executed) - -# if error: -# assert error in executed["errors"][0]["message"] -# else: -# assert executed["data"]["node"]["id"] == to_global_id( -# "BranchInversionSource", -# f"{model_version}:{branch_set_short_name}:{from_global_id(nrml_id)[1]}", -# ) -# assert executed["data"]["node"]["model_version"] == model_version -# assert ( -# executed["data"]["node"]["branch_set_short_name"] == branch_set_short_name -# ) -# assert executed["data"]["node"]["nrml_id"] == nrml_id -# assert executed["data"]["node"]["rupture_set_id"] == rupture_set_id diff --git a/tests/test_schema_source_models_as_relay_node.py b/tests/test_schema_source_models_as_relay_node.py new file mode 100644 index 0000000..d308ee1 --- /dev/null +++ b/tests/test_schema_source_models_as_relay_node.py @@ -0,0 +1,213 @@ +import pytest +from graphene.test import Client +from graphql_relay import to_global_id + +from nshm_model_graphql_api import schema + + +@pytest.fixture(scope="module") +def client(): + return Client(schema.schema_root) + + +@pytest.mark.parametrize( + "model_version", + ["NSHM_v1.0.0", "NSHM_v1.0.4"], +) +def test_get_model_SourceLogicTree_as_node(client, model_version): + QUERY = """ + query { + node(id: "%s") + { + ... on Node { + id + } + ... on SourceLogicTree { + model_version + } + } + } + """ % to_global_id( + "SourceLogicTree", model_version + ) + print(QUERY) + executed = client.execute(QUERY) + print(executed) + assert executed["data"]["node"]["model_version"] == model_version + assert executed["data"]["node"]["id"] == to_global_id( + "SourceLogicTree", model_version + ) + + +@pytest.mark.parametrize( + "model_version, short_name, long_name", + [ + ("NSHM_v1.0.0", "CRU", "Crustal"), + ("NSHM_v1.0.0", "PUY", "Puysegur"), + ("NSHM_v1.0.4", "CRU", "Crustal"), + ("NSHM_v1.0.4", "PUY", "Puysegur"), + ], +) +def test_get_model_SourceBranchSet_as_node( + client, model_version, short_name, long_name +): + QUERY = """ + query { + node(id: "%s") + { + ... on Node { + id + } + ... on SourceBranchSet { + model_version + short_name + long_name + } + + } + } + """ % to_global_id( + "SourceBranchSet", f"{model_version}:{short_name}" + ) + executed = client.execute(QUERY) + print(executed) + assert executed["data"]["node"]["model_version"] == model_version + assert executed["data"]["node"]["short_name"] == short_name + assert executed["data"]["node"]["long_name"] == long_name + assert executed["data"]["node"]["id"] == to_global_id( + "SourceBranchSet", f"{model_version}:{short_name}" + ) + + +@pytest.mark.parametrize( + "model_version, branch_set_short_name, tag, weight", + [ + ( + "NSHM_v1.0.0", + "CRU", + "[dmgeologic, tdFalse, bN[1.089, 4.6], C4.2, s1.0]", + 0.00541000379473566, + ), + ("NSHM_v1.0.0", "PUY", "[dm0.7, bN[0.902, 4.6], C4.0, s0.28]", 0.21), + ( + "NSHM_v1.0.4", + "CRU", + "[dmgeologic, tdFalse, bN[1.089, 4.6], C4.2, s1.41]", + 0.00286782725429677, + ), + ("NSHM_v1.0.4", "PUY", "[dm0.7, bN[0.902, 4.6], C4.0, s0.28]", 0.21), + ], +) +def test_get_model_SourceLogicTreeBranch_as_node( + client, model_version, branch_set_short_name, tag, weight +): + QUERY = """ + query { + node(id: "%s") + { + ... on Node { + id + } + ... on SourceLogicTreeBranch { + model_version + branch_set_short_name + tag + weight + sources { + ... on BranchInversionSource { + nrml_id + } + } + } + + } + } + """ % to_global_id( + "SourceLogicTreeBranch", f"{model_version}:{branch_set_short_name}:{tag}" + ) + executed = client.execute(QUERY) + print(executed) + assert executed["data"]["node"]["id"] == to_global_id( + "SourceLogicTreeBranch", f"{model_version}:{branch_set_short_name}:{tag}" + ) + + assert executed["data"]["node"]["model_version"] == model_version + assert executed["data"]["node"]["branch_set_short_name"] == branch_set_short_name + assert executed["data"]["node"]["tag"] == tag + assert executed["data"]["node"]["weight"] == weight + + +# @pytest.mark.parametrize( +# "model_version, branch_set_short_name, nrml_id, rupture_set_id, error", +# [ +# ( +# "NSHM_v1.0.0", +# "CRU", +# "SW52ZXJzaW9uU29sdXRpb25Ocm1sOjEyMDg5Mg==", +# "RmlsZToxMDAwODc=", +# None, +# ), +# ( +# "NSHM_v1.0.0", +# "PUY", +# "SW52ZXJzaW9uU29sdXRpb25Ocm1sOjExODcxNw==", +# "RmlsZToxNzU3My4wQUYzU1o=", +# None, +# ), +# ( +# "NSHM_v1.0.4", +# "CRU", +# "SW52ZXJzaW9uU29sdXRpb25Ocm1sOjEyOTE0ODY=", +# "RmlsZToxMDAwODc=", +# None, +# ), +# ( +# "NSHM_v1.0.0", +# "CRU", +# "SW52ZXJzaW9uU29sdXRpb25Ocm1sOjEyOTE0ODY=", +# "", +# "`NSHM_v1.0.0:CRU:1291486` was not found", +# ), +# ], +# ) +# def test_get_model_BranchInversionSource_as_node( +# client, model_version, branch_set_short_name, nrml_id, rupture_set_id, error +# ): +# QUERY = """ +# query { +# node(id: "%s") +# { +# ... on Node { +# id +# } +# ... on BranchInversionSource { +# model_version +# branch_set_short_name +# nrml_id +# rupture_set_id +# } + +# } +# } +# """ % to_global_id( +# "BranchInversionSource", +# f"{model_version}:{branch_set_short_name}:{from_global_id(nrml_id)[1]}", +# ) + +# print(QUERY) +# executed = client.execute(QUERY) +# print(executed) + +# if error: +# assert error in executed["errors"][0]["message"] +# else: +# assert executed["data"]["node"]["id"] == to_global_id( +# "BranchInversionSource", +# f"{model_version}:{branch_set_short_name}:{from_global_id(nrml_id)[1]}", +# ) +# assert executed["data"]["node"]["model_version"] == model_version +# assert ( +# executed["data"]["node"]["branch_set_short_name"] == branch_set_short_name +# ) +# assert executed["data"]["node"]["nrml_id"] == nrml_id +# assert executed["data"]["node"]["rupture_set_id"] == rupture_set_id From cdc088f89cf847d80fb039cbae90694b1cadf7b4 Mon Sep 17 00:00:00 2001 From: Chris Chamberlain Date: Fri, 7 Jun 2024 16:24:29 +1200 Subject: [PATCH 2/3] update nzshm-model; use branch_set short_name for GMM node identity resolvers;update tests; --- CHANGELOG.md | 3 +- .../schema/nshm_model_gmms_schema.py | 45 ++++++++-------- poetry.lock | 4 +- tests/test_schema_gmm_models_as_relay_node.py | 53 +++++++++---------- tests/test_schema_model_gmm_logic_tree.py | 7 +-- 5 files changed, 55 insertions(+), 57 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 202f463..096b8b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -## [0.2.0] - 2024-05-30 +## [0.2.0] - 2024-06-07 ### Changed - Complete reset, no more django - all previous code is mothballed @@ -13,6 +13,7 @@ - get_model resolver - get_models resolver - source logic tree models and resolvers + - gmmm logic tree models and resolvers ## [0.1.3] - 2023-09-04 ### Added diff --git a/nshm_model_graphql_api/schema/nshm_model_gmms_schema.py b/nshm_model_graphql_api/schema/nshm_model_gmms_schema.py index e16299c..1b8d8cf 100644 --- a/nshm_model_graphql_api/schema/nshm_model_gmms_schema.py +++ b/nshm_model_graphql_api/schema/nshm_model_gmms_schema.py @@ -1,5 +1,6 @@ """Define graphene model for nzshm_model gmm logic tree classes.""" +import json import logging from functools import lru_cache @@ -13,26 +14,25 @@ # TODO: this method belongs on the nzshm-model gmcm class @lru_cache -def get_branch_set(model_version, tectonic_region_type): +def get_branch_set(model_version, short_name): glt = get_model_by_version(model_version).gmm_logic_tree log.debug(f"glt {glt}") for bs in glt.branch_sets: - if bs.tectonic_region_type == tectonic_region_type: + if bs.short_name == short_name: return bs - assert 0, f"branch set {tectonic_region_type} was not found" # pragma: no cover + assert 0, f"branch set {short_name} was not found" # pragma: no cover # TODO: this method belongs on the nzshm-model gmcm class @lru_cache -def get_logic_tree_branch(model_version, branch_set_trt, gsim_name, gsim_args): +def get_logic_tree_branch(model_version, branch_set_short_name, gsim_name, gsim_args): log.info( - f"get_logic_tree_branch: {branch_set_trt} gsim_name: {gsim_name} gsim_args: {gsim_args}" + f"get_logic_tree_branch: {branch_set_short_name} gsim_name: {gsim_name} gsim_args: {gsim_args}" ) - branch_set = get_branch_set(model_version, branch_set_trt) + branch_set = get_branch_set(model_version, branch_set_short_name) for ltb in branch_set.branches: - if (ltb.gsim_name == gsim_name) and (str(ltb.gsim_args) == gsim_args): + if (ltb.gsim_name == gsim_name) and (ltb.gsim_args == json.loads(gsim_args)): return ltb - print(branch_set_trt, ltb.tag) assert ( 0 ), f"branch with gsim_name: {gsim_name} gsim_args: {gsim_args} was not found" # pragma: no cover @@ -43,26 +43,26 @@ class Meta: interfaces = (relay.Node,) model_version = graphene.String() - branch_set_trt = graphene.String() + branch_set_short_name = graphene.String() gsim_name = graphene.String() gsim_args = graphene.String() tectonic_region_type = graphene.String() # should be an enum weight = graphene.Float() def resolve_id(self, info): - return f"{self.model_version}:{self.branch_set_trt}:{self.gsim_name}:{self.gsim_args}" + return f"{self.model_version}|{self.branch_set_short_name}|{self.gsim_name}|{self.gsim_args}" @classmethod def get_node(cls, info, node_id: str): - model_version, branch_set_trt, gsim_name, gsim_args = node_id.split(":") + model_version, branch_set_short_name, gsim_name, gsim_args = node_id.split("|") gltb = get_logic_tree_branch( - model_version, branch_set_trt, gsim_name, gsim_args + model_version, branch_set_short_name, gsim_name, gsim_args ) return GmmLogicTreeBranch( model_version=model_version, - branch_set_trt=branch_set_trt, - gsim_name=gsim_name, - gsim_args=gsim_args, + branch_set_short_name=branch_set_short_name, + gsim_name=gltb.gsim_name, + gsim_args=json.dumps(gltb.gsim_args), weight=gltb.weight, ) @@ -83,15 +83,15 @@ class Meta: branches = graphene.List(GmmLogicTreeBranch) def resolve_id(self, info): - return f"{self.model_version}:{self.tectonic_region_type}" + return f"{self.model_version}:{self.short_name}" @classmethod def get_node(cls, info, node_id: str): - model_version, tectonic_region_type = node_id.split(":") - bs = get_branch_set(model_version, tectonic_region_type) + model_version, short_name = node_id.split(":") + bs = get_branch_set(model_version, short_name) return GmmBranchSet( model_version=model_version, - tectonic_region_type=tectonic_region_type, + tectonic_region_type=bs.tectonic_region_type, short_name=bs.short_name, long_name=bs.long_name, ) @@ -99,17 +99,16 @@ def get_node(cls, info, node_id: str): @staticmethod def resolve_branches(root, info, **kwargs): log.info(f"resolve_branches root: {root} kwargs: {kwargs}") - bs = get_branch_set(root.model_version, root.tectonic_region_type) + bs = get_branch_set(root.model_version, root.short_name) for ltb in bs.branches: log.debug(ltb) - ltb = GmmLogicTreeBranch( + yield GmmLogicTreeBranch( model_version=root.model_version, tectonic_region_type=root.tectonic_region_type, weight=ltb.weight, gsim_name=ltb.gsim_name, gsim_args=str(ltb.gsim_args), ) - yield ltb class GroundMotionModelLogicTree(graphene.ObjectType): @@ -135,5 +134,7 @@ def resolve_branch_sets(root, info, **kwargs): for bs in glt.branch_sets: yield GmmBranchSet( model_version=root.model_version, + short_name=bs.short_name, + long_name=bs.long_name, tectonic_region_type=bs.tectonic_region_type, ) diff --git a/poetry.lock b/poetry.lock index 9a94b6a..375817a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -844,7 +844,7 @@ files = [ [[package]] name = "nzshm-model" -version = "0.10.4" +version = "0.10.5" description = "The logic tree definitions, final configurations, and versioning of the New Zealand | Aotearoa National Seismic Hazard Model" optional = false python-versions = ">=3.9,<4.0" @@ -867,7 +867,7 @@ toshi = ["boto3[toshi] (>=1.26.28,<2.0.0)", "nshm-toshi-client[toshi] (>=1.0.1,< type = "git" url = "https://github.com/GNS-Science/nzshm-model" reference = "pre-release" -resolved_reference = "f79458021def6b52fe2cad3ccbbfdf1bc084ae8e" +resolved_reference = "c16652f9d92ccc8d2f66a1e6750d56945dbcafb7" [[package]] name = "packaging" diff --git a/tests/test_schema_gmm_models_as_relay_node.py b/tests/test_schema_gmm_models_as_relay_node.py index f65831d..6f648c1 100644 --- a/tests/test_schema_gmm_models_as_relay_node.py +++ b/tests/test_schema_gmm_models_as_relay_node.py @@ -42,10 +42,10 @@ def test_get_model_SourceLogicTree_as_node(client, model_version): @pytest.mark.parametrize( "model_version, short_name, long_name", [ - ("NSHM_v1.0.0", "Active Shallow Crust", "Crustal"), - # ("NSHM_v1.0.0", "PUY", "Puysegur"), - # ("NSHM_v1.0.4", "CRU", "Crustal"), - # ("NSHM_v1.0.4", "PUY", "Puysegur"), + ("NSHM_v1.0.0", "CRU", "Crustal"), + ("NSHM_v1.0.0", "SLAB", "Subduction Intraslab"), + ("NSHM_v1.0.4", "CRU", "Crustal"), + ("NSHM_v1.0.4", "INTER", "Subduction Interface"), ], ) def test_get_model_GmmBranchSet_as_node(client, model_version, short_name, long_name): @@ -71,36 +71,34 @@ def test_get_model_GmmBranchSet_as_node(client, model_version, short_name, long_ executed = client.execute(QUERY) print(executed) assert executed["data"]["node"]["model_version"] == model_version - assert executed["data"]["node"]["tectonic_region_type"] == short_name - # assert executed["data"]["node"]["long_name"] == long_name + assert executed["data"]["node"]["short_name"] == short_name + assert executed["data"]["node"]["long_name"] == long_name assert executed["data"]["node"]["id"] == to_global_id( "GmmBranchSet", f"{model_version}:{short_name}" ) -''' - @pytest.mark.parametrize( - "model_version, branch_set_short_name, tag, weight", + "model_version, branch_set_short_name, gsim_name, gsim_args, weight", [ ( "NSHM_v1.0.0", "CRU", - "[dmgeologic, tdFalse, bN[1.089, 4.6], C4.2, s1.0]", - 0.00541000379473566, + "Stafford2022", + '{"mu_branch": "Upper"}', + 0.117, ), - ("NSHM_v1.0.0", "PUY", "[dm0.7, bN[0.902, 4.6], C4.0, s0.28]", 0.21), ( "NSHM_v1.0.4", - "CRU", - "[dmgeologic, tdFalse, bN[1.089, 4.6], C4.2, s1.41]", - 0.00286782725429677, + "INTER", + "Atkinson2022SInter", + '{"epistemic": "Lower", "modified_sigma": "true"}', + 0.081, ), - ("NSHM_v1.0.4", "PUY", "[dm0.7, bN[0.902, 4.6], C4.0, s0.28]", 0.21), ], ) -def test_get_model_SourceLogicTreeBranch_as_node( - client, model_version, branch_set_short_name, tag, weight +def test_get_model_GmmLogicTreeBranch_as_node( + client, model_version, branch_set_short_name, gsim_name, gsim_args, weight ): QUERY = """ query { @@ -109,31 +107,28 @@ def test_get_model_SourceLogicTreeBranch_as_node( ... on Node { id } - ... on SourceLogicTreeBranch { + ... on GmmLogicTreeBranch { model_version branch_set_short_name - tag + gsim_name + gsim_args weight - sources { - ... on BranchInversionSource { - nrml_id - } - } } } } """ % to_global_id( - "SourceLogicTreeBranch", f"{model_version}:{branch_set_short_name}:{tag}" + "GmmLogicTreeBranch", + f"{model_version}|{branch_set_short_name}|{gsim_name}|{gsim_args}", ) executed = client.execute(QUERY) print(executed) assert executed["data"]["node"]["id"] == to_global_id( - "SourceLogicTreeBranch", f"{model_version}:{branch_set_short_name}:{tag}" + "GmmLogicTreeBranch", + f"{model_version}|{branch_set_short_name}|{gsim_name}|{gsim_args}", ) assert executed["data"]["node"]["model_version"] == model_version assert executed["data"]["node"]["branch_set_short_name"] == branch_set_short_name - assert executed["data"]["node"]["tag"] == tag + assert executed["data"]["node"]["gsim_name"] == gsim_name assert executed["data"]["node"]["weight"] == weight -''' diff --git a/tests/test_schema_model_gmm_logic_tree.py b/tests/test_schema_model_gmm_logic_tree.py index ad6a860..a4a3c20 100644 --- a/tests/test_schema_model_gmm_logic_tree.py +++ b/tests/test_schema_model_gmm_logic_tree.py @@ -25,8 +25,8 @@ def test_get_model_and_branch_sets(client, model_version): branch_sets { __typename model_version - # short_name - # long_name + short_name + long_name tectonic_region_type } } @@ -44,7 +44,8 @@ def test_get_model_and_branch_sets(client, model_version): assert branch_sets[0]["__typename"] == "GmmBranchSet" assert branch_sets[0]["model_version"] == model_version assert branch_sets[0]["tectonic_region_type"] == "Active Shallow Crust" - # assert branch_sets[0]["short_name"] == "PUY" + assert branch_sets[0]["short_name"] == "CRU" + assert branch_sets[0]["long_name"] == "Crustal" @pytest.mark.parametrize( From 7b65d8d5a904d0219a6bcfdf82e1db9f457f7130 Mon Sep 17 00:00:00 2001 From: Chris Chamberlain Date: Fri, 7 Jun 2024 16:49:12 +1200 Subject: [PATCH 3/3] fix branch_set_short_name attrinute and tests --- .../schema/nshm_model_gmms_schema.py | 12 +++++++----- tests/test_schema_model_gmm_logic_tree.py | 13 ++++++++----- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/nshm_model_graphql_api/schema/nshm_model_gmms_schema.py b/nshm_model_graphql_api/schema/nshm_model_gmms_schema.py index 1b8d8cf..f318d63 100644 --- a/nshm_model_graphql_api/schema/nshm_model_gmms_schema.py +++ b/nshm_model_graphql_api/schema/nshm_model_gmms_schema.py @@ -45,12 +45,12 @@ class Meta: model_version = graphene.String() branch_set_short_name = graphene.String() gsim_name = graphene.String() - gsim_args = graphene.String() + gsim_args = graphene.JSONString() tectonic_region_type = graphene.String() # should be an enum weight = graphene.Float() def resolve_id(self, info): - return f"{self.model_version}|{self.branch_set_short_name}|{self.gsim_name}|{self.gsim_args}" + return f"{self.model_version}|{self.branch_set_short_name}|{self.gsim_name}|{json.dumps(self.gsim_args)}" @classmethod def get_node(cls, info, node_id: str): @@ -61,8 +61,9 @@ def get_node(cls, info, node_id: str): return GmmLogicTreeBranch( model_version=model_version, branch_set_short_name=branch_set_short_name, + tectonic_region_type=gltb.tectonic_region_type, gsim_name=gltb.gsim_name, - gsim_args=json.dumps(gltb.gsim_args), + gsim_args=gltb.gsim_args, weight=gltb.weight, ) @@ -104,10 +105,11 @@ def resolve_branches(root, info, **kwargs): log.debug(ltb) yield GmmLogicTreeBranch( model_version=root.model_version, - tectonic_region_type=root.tectonic_region_type, + branch_set_short_name=root.short_name, + tectonic_region_type=ltb.tectonic_region_type, weight=ltb.weight, gsim_name=ltb.gsim_name, - gsim_args=str(ltb.gsim_args), + gsim_args=ltb.gsim_args, ) diff --git a/tests/test_schema_model_gmm_logic_tree.py b/tests/test_schema_model_gmm_logic_tree.py index a4a3c20..f6e0bd9 100644 --- a/tests/test_schema_model_gmm_logic_tree.py +++ b/tests/test_schema_model_gmm_logic_tree.py @@ -1,3 +1,5 @@ +import json + import pytest from graphene.test import Client @@ -66,7 +68,7 @@ def test_get_model_and_branch_set_branches(client, model_version): # short_name branches { __typename - # branch_set_short_name + branch_set_short_name model_version weight gsim_name @@ -86,10 +88,11 @@ def test_get_model_and_branch_set_branches(client, model_version): print(executed) branch_sets = executed["data"]["get_model"]["gmm_logic_tree"]["branch_sets"] # assert branch_sets[0]["short_name"] == "PUY" + assert branch_sets[0]["branches"][0]["__typename"] == "GmmLogicTreeBranch" assert branch_sets[0]["branches"][0]["weight"] <= 1.0 + assert branch_sets[0]["branches"][0]["branch_set_short_name"] == "CRU" assert branch_sets[0]["branches"][0]["gsim_name"] == "Stafford2022" - assert branch_sets[0]["branches"][0]["gsim_args"] == "{'mu_branch': 'Upper'}" - - assert branch_sets[0]["branches"][0]["__typename"] == "GmmLogicTreeBranch" + assert branch_sets[0]["branches"][0]["gsim_args"] == json.dumps( + {"mu_branch": "Upper"} + ) assert branch_sets[0]["branches"][0]["model_version"] == model_version - # assert branch_sets[0]["branches"][0]["branch_set_short_name"] == "PUY"