From 4404e86bf24177abc6dbf7cbd7470b1642f33480 Mon Sep 17 00:00:00 2001 From: wolandscat Date: Wed, 7 Aug 2024 13:57:16 -0600 Subject: [PATCH] Initial working version of archetype lib statistical report. --- .../src/gui/library_tool/gui_library_tool.e | 40 ++++----- ...cs_tool.e => gui_compilation_stats_tool.e} | 4 +- .../src/gui/main/gui_error_tool.e | 6 +- apps/adlc/src/main/application.e | 5 ++ .../archetype_library_stats_report_builder.e | 84 +++++++++++++++++++ .../messages/compiled/adl_messages_db.e | 13 +-- .../messages/compiled/adl_messages_ids.e | 3 +- .../messages/source/adl_compiler_errors.txt | 11 +-- .../archetype_library_stats_report.e | 39 +++++++++ .../src/interface/archetype_reporter.e | 1 + .../src/interface/report_data_group.e | 7 ++ .../src/interface/report_data_node.e | 21 ++++- .../src/interface/value_sets_report.e | 34 +++++--- .../src/library/archetype_library.e | 34 ++++---- .../library/archetype_library_statistics.e | 41 +++++++++ .../archetype_statistical_analyser.e | 22 ++--- .../archetype_statistical_definitions.e | 16 ++-- .../statistics/reported_statistical_datum.e | 44 ++++++++++ .../src/statistics/statistical_datum.e | 7 ++ 19 files changed, 351 insertions(+), 81 deletions(-) rename apps/adl_workbench/src/gui/main/{gui_statistics_tool.e => gui_compilation_stats_tool.e} (98%) mode change 100755 => 100644 create mode 100644 apps/adlc/src/main/archetype_library_stats_report_builder.e create mode 100644 components/adl_compiler/src/interface/archetype_library_stats_report.e create mode 100644 components/archetype_repository/src/library/archetype_library_statistics.e create mode 100644 components/archetype_repository/src/statistics/reported_statistical_datum.e diff --git a/apps/adl_workbench/src/gui/library_tool/gui_library_tool.e b/apps/adl_workbench/src/gui/library_tool/gui_library_tool.e index 50ab1e1b0..5be1326c3 100755 --- a/apps/adl_workbench/src/gui/library_tool/gui_library_tool.e +++ b/apps/adl_workbench/src/gui/library_tool/gui_library_tool.e @@ -60,8 +60,8 @@ feature {NONE} -- Initialisation create archetype_explorer.make create template_explorer.make - create metrics_viewer.make - create stats_viewer.make + create compilation_stats_viewer.make + create archetypes_stats_viewer.make -- create widgets create ev_root_container @@ -80,12 +80,12 @@ feature {NONE} -- Initialisation ev_notebook.set_item_text (template_explorer.ev_root_container, get_text ({ADL_MESSAGES_IDS}.ec_library_template_tab_text)) -- metrics viewer tab - ev_notebook.extend (metrics_viewer.ev_root_container) - ev_notebook.set_item_text (metrics_viewer.ev_root_container, get_text ({ADL_MESSAGES_IDS}.ec_library_metrics_tab_text)) + ev_notebook.extend (compilation_stats_viewer.ev_root_container) + ev_notebook.set_item_text (compilation_stats_viewer.ev_root_container, get_text ({ADL_MESSAGES_IDS}.ec_library_metrics_tab_text)) -- statistics viewer tab - ev_notebook.extend (stats_viewer.ev_root_container) - ev_notebook.set_item_text (stats_viewer.ev_root_container, get_text ({ADL_MESSAGES_IDS}.ec_library_stats_tab_text)) + ev_notebook.extend (archetypes_stats_viewer.ev_root_container) + ev_notebook.set_item_text (archetypes_stats_viewer.ev_root_container, get_text ({ADL_MESSAGES_IDS}.ec_library_stats_tab_text)) set_tabs_appearance @@ -137,8 +137,8 @@ feature {NONE} -- Initialisation -- set up tool / sub-tool structures add_sub_tool (archetype_explorer) add_sub_tool (template_explorer) - add_sub_tool (metrics_viewer) - add_sub_tool (stats_viewer) + add_sub_tool (compilation_stats_viewer) + add_sub_tool (archetypes_stats_viewer) enable_selection_history ev_root_container.set_data (Current) @@ -321,13 +321,13 @@ feature -- Events on_select_notebook do if attached source as src and attached ev_notebook.selected_item as sel_item and then attached sel_item.data as att_data then - if att_data = metrics_viewer then + if att_data = compilation_stats_viewer then if src.can_build_statistics then - metrics_viewer.populate (src) + compilation_stats_viewer.populate (src) end - elseif att_data = stats_viewer then + elseif att_data = archetypes_stats_viewer then if src.can_build_statistics then - stats_viewer.populate (src.statistics, True) + archetypes_stats_viewer.populate (src.archetype_statistics, True) end end end @@ -382,8 +382,8 @@ feature {NONE} -- Implementation do_clear do - metrics_viewer.clear - stats_viewer.clear + compilation_stats_viewer.clear + archetypes_stats_viewer.clear archetype_explorer.clear ev_notebook.select_item (archetype_explorer.ev_root_container) end @@ -448,19 +448,19 @@ feature {NONE} -- Implementation template_explorer: GUI_TEMPLATE_EXPLORER - metrics_viewer: GUI_STATISTICS_TOOL + compilation_stats_viewer: GUI_COMPILATION_STATS_TOOL - stats_viewer: GUI_ARCHETYPE_STATISTICAL_REPORT + archetypes_stats_viewer: GUI_ARCHETYPE_STATISTICAL_REPORT set_tabs_appearance -- set visual appearance of stats & metric tab according to whether there are errors or not do if attached source as src and then src.can_build_statistics then - ev_notebook.item_tab (metrics_viewer.ev_root_container).set_pixmap (get_icon_pixmap ("tool/metrics")) - ev_notebook.item_tab (stats_viewer.ev_root_container).set_pixmap (get_icon_pixmap ("tool/statistics")) + ev_notebook.item_tab (compilation_stats_viewer.ev_root_container).set_pixmap (get_icon_pixmap ("tool/metrics")) + ev_notebook.item_tab (archetypes_stats_viewer.ev_root_container).set_pixmap (get_icon_pixmap ("tool/statistics")) else - ev_notebook.item_tab (metrics_viewer.ev_root_container).set_pixmap (get_icon_pixmap ("tool/metrics_grey")) - ev_notebook.item_tab (stats_viewer.ev_root_container).set_pixmap (get_icon_pixmap ("tool/statistics_grey")) + ev_notebook.item_tab (compilation_stats_viewer.ev_root_container).set_pixmap (get_icon_pixmap ("tool/metrics_grey")) + ev_notebook.item_tab (archetypes_stats_viewer.ev_root_container).set_pixmap (get_icon_pixmap ("tool/statistics_grey")) end if attached source as src and then src.template_count > 0 then ev_notebook.item_tab (template_explorer.ev_root_container).set_pixmap (get_icon_pixmap ("tool/template_catalog")) diff --git a/apps/adl_workbench/src/gui/main/gui_statistics_tool.e b/apps/adl_workbench/src/gui/main/gui_compilation_stats_tool.e old mode 100755 new mode 100644 similarity index 98% rename from apps/adl_workbench/src/gui/main/gui_statistics_tool.e rename to apps/adl_workbench/src/gui/main/gui_compilation_stats_tool.e index 942e7f11a..98f563091 --- a/apps/adl_workbench/src/gui/main/gui_statistics_tool.e +++ b/apps/adl_workbench/src/gui/main/gui_compilation_stats_tool.e @@ -7,7 +7,7 @@ note copyright: "Copyright (c) 2011 openEHR Foundation " license: "Apache 2.0 License " -class GUI_STATISTICS_TOOL +class GUI_COMPILATION_STATS_TOOL inherit GUI_LIBRARY_TARGETTED_TOOL @@ -65,7 +65,7 @@ feature {NONE} -- Implementation <> ) - populate_ev_multi_list_from_hash (ev_stats_mlist, safe_source.metrics) + populate_ev_multi_list_from_hash (ev_stats_mlist, safe_source.compilation_statistics) ev_stats_info_frame.set_minimum_height ((ev_stats_mlist.count + 3) * ev_stats_mlist.row_height) -- do terminology bindings statistics diff --git a/apps/adl_workbench/src/gui/main/gui_error_tool.e b/apps/adl_workbench/src/gui/main/gui_error_tool.e index 5890038eb..6250a41b9 100755 --- a/apps/adl_workbench/src/gui/main/gui_error_tool.e +++ b/apps/adl_workbench/src/gui/main/gui_error_tool.e @@ -212,9 +212,9 @@ feature -- Commands create statistics_element.make_last (root, "statistics", ns) create_category_element.call ([statistics_element, "Total Archetypes", current_library.archetype_count]) - create_category_element.call ([statistics_element, "Specialised Archetypes", current_library.metrics.item (specialised_archetype_count)]) - create_category_element.call ([statistics_element, "Archetypes with slots", current_library.metrics.item (client_archetype_count)]) - create_category_element.call ([statistics_element, "Archetypes used by others", current_library.metrics.item (supplier_archetype_count)]) + create_category_element.call ([statistics_element, "Specialised Archetypes", current_library.compilation_statistics.item (specialised_archetype_count)]) + create_category_element.call ([statistics_element, "Archetypes with slots", current_library.compilation_statistics.item (client_archetype_count)]) + create_category_element.call ([statistics_element, "Archetypes used by others", current_library.compilation_statistics.item (supplier_archetype_count)]) from err_type := categories.lower until err_type = categories.upper loop err_type := err_type + 1 diff --git a/apps/adlc/src/main/application.e b/apps/adlc/src/main/application.e index 04bf00ef1..49968442a 100755 --- a/apps/adlc/src/main/application.e +++ b/apps/adlc/src/main/application.e @@ -340,6 +340,7 @@ feature -- Commands generate_library_reports local lib_name, full_output_dir, full_path, schema_file_path, export_dir: STRING + arch_lib_stats_rpt_builder: ARCHETYPE_LIBRARY_STATS_REPORT_BUILDER do -- OPTION: output format if attached opts.output_format as of then @@ -372,6 +373,10 @@ feature -- Commands report_std_out ("--------- Generating reports in " + full_output_dir + " ---------") archetype_reporter.build_all end + + -- PROCESS special reports + create arch_lib_stats_rpt_builder.make (full_output_dir, agent report_std_out, agent report_std_err, agent :BOOLEAN do Result := error_reported end) + arch_lib_stats_rpt_builder.execute end feature {NONE} -- Commands diff --git a/apps/adlc/src/main/archetype_library_stats_report_builder.e b/apps/adlc/src/main/archetype_library_stats_report_builder.e new file mode 100644 index 000000000..c5408b7a2 --- /dev/null +++ b/apps/adlc/src/main/archetype_library_stats_report_builder.e @@ -0,0 +1,84 @@ +note + component: "openEHR ADL Tools" + description : "Terminology bindings exporter" + keywords: "ADL, archetype, compiler, command line" + author: "Thomas Beale " + support: "http://www.openehr.org/issues/browse/AWB" + copyright: "Copyright (c) 2024- Graphite Health " + license: "Apache 2.0 License " + +class + ARCHETYPE_LIBRARY_STATS_REPORT_BUILDER + +inherit + CLI_COMMAND + rename + make as make_cli + end + +create + make + +feature -- Initialization + + make (an_output_dir: STRING; report_std_out_agt, report_std_err_agt: PROCEDURE [ANY, TUPLE[STRING]]; an_error_reported_agt: FUNCTION[ANY, TUPLE[], BOOLEAN]) + do + make_cli (report_std_out_agt, report_std_err_agt, an_error_reported_agt) + + output_dir := an_output_dir + if not file_system.is_absolute_pathname (output_dir) then + output_dir := file_system.pathname (file_system.current_working_directory, output_dir) + end + file_system.recursive_create_directory (output_dir) + if not file_system.directory_exists (output_dir) then + report_std_err (get_msg ({ADL_MESSAGES_IDS}.ec_invalid_output_directory, <>)) + end + end + +feature -- Commands + + execute + -- export all term bindings into one files per terminology namespace + -- Each file is a CSV file of the form + -- archetype_id, archetype_node_id, binding_value + local + out_file: KI_TEXT_OUTPUT_FILE + row_str: STRING + arch_stats_report: ARCHETYPE_LIBRARY_STATS_REPORT + arch_lib_stats: ARCHETYPE_LIBRARY_STATISTICS + do + report_std_out ("--------- Writing statistical report to " + output_dir + "---------") + + create arch_stats_report.make ("Arch_lib_stats_report") + arch_stats_report.compilation_statistics.merge (current_library.compilation_statistics) + across current_library.archetype_statistics as reports_csr loop + create arch_lib_stats.make (current_library_name, reports_csr.key) + arch_lib_stats.add_model_statistics (reports_csr.item.archetype_metrics) + arch_stats_report.add_models_report (arch_lib_stats, reports_csr.key) + end + + out_file := file_system.new_output_file (file_system.pathname (output_dir, arch_stats_report.id + ".json")) + out_file.open_write + output_to_json (arch_stats_report, out_file) + out_file.close + end + +feature {NONE} -- Commands + + output_dir: STRING + + output_to_json (rpt: REPORT_DATA; fd: KI_TEXT_OUTPUT_FILE) + local + fac: JSON_SERIALIZATION_FACTORY + conv: JSON_SERIALIZATION + do + conv := fac.smart_serialization + conv.set_pretty_printing + conv.context.serializer_context.set_is_type_name_included (False) + + if attached conv.to_json_string (rpt) as s then + fd.put_string (s) + end + end + +end diff --git a/apps/resources/messages/compiled/adl_messages_db.e b/apps/resources/messages/compiled/adl_messages_db.e index d8c80b140..ee275459b 100755 --- a/apps/resources/messages/compiled/adl_messages_db.e +++ b/apps/resources/messages/compiled/adl_messages_db.e @@ -24,7 +24,7 @@ feature -- Initialisation make do - create message_table.make (976) + create message_table.make (977) message_table.put ("Terminology initialisation failed; reason: $1", ec_terminology_init_failed) message_table.put ("Using ADL version $1 for output serialisation", ec_adl_version_warning) message_table.put ("Validation level STRICT", ec_validation_strict) @@ -81,14 +81,15 @@ feature -- Initialisation message_table.put ("Archetype at $1 invalid identifier $2", ec_parse_archetype_e8) message_table.put ("Archetype at $1 invalid artefact type $2 (should be 'archetype', 'template', etc)", ec_parse_archetype_e9) message_table.put ("Archetype at $1 invalid parent identifier $2", ec_parse_archetype_e10) - message_table.put ("Object nodes", ec_arch_stats_object_nodes_text) + message_table.put ("Total nodes", ec_arch_stats_object_nodes_text) message_table.put ("Archetypable nodes", ec_arch_stats_archetypable_nodes_text) message_table.put ("Data value nodes", ec_arch_stats_data_value_nodes_text) - message_table.put ("Id-codes", ec_arch_stats_id_codes_text) - message_table.put ("At-codes", ec_arch_stats_at_codes_text) - message_table.put ("Ac-codes", ec_arch_stats_ac_codes_text) - message_table.put ("At-code bindings", ec_arch_stats_at_code_bindings_text) + message_table.put ("Id-codes (semantic)", ec_arch_stats_id_codes_text) + message_table.put ("At-codes (coded values)", ec_arch_stats_at_codes_text) + message_table.put ("Ac-codes (value-sets)", ec_arch_stats_ac_codes_text) + message_table.put ("Id-code bindings", ec_arch_stats_id_code_bindings_text) message_table.put ("Ac-code bindings", ec_arch_stats_ac_code_bindings_text) + message_table.put ("At-code bindings", ec_arch_stats_at_code_bindings_text) message_table.put ("Total archetypes", ec_arch_stats_total_archetypes_text) message_table.put ("Valid archetypes", ec_arch_stats_valid_archetypes_text) message_table.put ("Specialised archetypes", ec_arch_stats_specialised_archetypes_text) diff --git a/apps/resources/messages/compiled/adl_messages_ids.e b/apps/resources/messages/compiled/adl_messages_ids.e index 54d02c278..cf9629931 100755 --- a/apps/resources/messages/compiled/adl_messages_ids.e +++ b/apps/resources/messages/compiled/adl_messages_ids.e @@ -72,8 +72,9 @@ feature -- Definitions ec_arch_stats_id_codes_text: STRING = "arch_stats_id_codes_text" ec_arch_stats_at_codes_text: STRING = "arch_stats_at_codes_text" ec_arch_stats_ac_codes_text: STRING = "arch_stats_ac_codes_text" - ec_arch_stats_at_code_bindings_text: STRING = "arch_stats_at_code_bindings_text" + ec_arch_stats_id_code_bindings_text: STRING = "arch_stats_id_code_bindings_text" ec_arch_stats_ac_code_bindings_text: STRING = "arch_stats_ac_code_bindings_text" + ec_arch_stats_at_code_bindings_text: STRING = "arch_stats_at_code_bindings_text" ec_arch_stats_total_archetypes_text: STRING = "arch_stats_total_archetypes_text" ec_arch_stats_valid_archetypes_text: STRING = "arch_stats_valid_archetypes_text" ec_arch_stats_specialised_archetypes_text: STRING = "arch_stats_specialised_archetypes_text" diff --git a/apps/resources/messages/source/adl_compiler_errors.txt b/apps/resources/messages/source/adl_compiler_errors.txt index 4f4d3aa56..6c7c0f42c 100755 --- a/apps/resources/messages/source/adl_compiler_errors.txt +++ b/apps/resources/messages/source/adl_compiler_errors.txt @@ -91,14 +91,15 @@ templates = < ["parse_archetype_e10"] = <"Archetype at $1 invalid parent identifier $2"> -- ARCHETYPE_STATISTICAL_DEFINITIONS - ["arch_stats_object_nodes_text"] = <"Object nodes"> + ["arch_stats_object_nodes_text"] = <"Total nodes"> ["arch_stats_archetypable_nodes_text"] = <"Archetypable nodes"> ["arch_stats_data_value_nodes_text"] = <"Data value nodes"> - ["arch_stats_id_codes_text"] = <"Id-codes"> - ["arch_stats_at_codes_text"] = <"At-codes"> - ["arch_stats_ac_codes_text"] = <"Ac-codes"> - ["arch_stats_at_code_bindings_text"] = <"At-code bindings"> + ["arch_stats_id_codes_text"] = <"Id-codes (semantic)"> + ["arch_stats_at_codes_text"] = <"At-codes (coded values)"> + ["arch_stats_ac_codes_text"] = <"Ac-codes (value-sets)"> + ["arch_stats_id_code_bindings_text"] = <"Id-code bindings"> ["arch_stats_ac_code_bindings_text"] = <"Ac-code bindings"> + ["arch_stats_at_code_bindings_text"] = <"At-code bindings"> ["arch_stats_total_archetypes_text"] = <"Total archetypes"> ["arch_stats_valid_archetypes_text"] = <"Valid archetypes"> ["arch_stats_specialised_archetypes_text"] = <"Specialised archetypes"> diff --git a/components/adl_compiler/src/interface/archetype_library_stats_report.e b/components/adl_compiler/src/interface/archetype_library_stats_report.e new file mode 100644 index 000000000..9d1a2331f --- /dev/null +++ b/components/adl_compiler/src/interface/archetype_library_stats_report.e @@ -0,0 +1,39 @@ +note + component: "openEHR ADL Tools" + description: "Archetype report data object" + keywords: "export, archetype, ADL" + author: "Thomas Beale " + support: "openEHR AWB project " + copyright: "Copyright (c) 2024 Graphite Health" + license: "Apache 2.0 License " + +class ARCHETYPE_LIBRARY_STATS_REPORT + +inherit + REPORT_DATA + +create + make + +feature -- Access + + compilation_statistics: HASH_TABLE [INTEGER, STRING] + -- Archetype library compilation stats + attribute + create Result.make(0) + end + + models_reports: HASH_TABLE [ARCHETYPE_LIBRARY_STATISTICS, STRING] + -- Archetype library model stats, grouped by Model name, e.g. 'EHR', 'ENTITY' etc + attribute + create Result.make(0) + end + +feature-- Modification + + add_models_report (a_report: ARCHETYPE_LIBRARY_STATISTICS; a_key: STRING) + do + models_reports.put (a_report, a_key) + end + +end diff --git a/components/adl_compiler/src/interface/archetype_reporter.e b/components/adl_compiler/src/interface/archetype_reporter.e index db90bb872..4206e64cb 100644 --- a/components/adl_compiler/src/interface/archetype_reporter.e +++ b/components/adl_compiler/src/interface/archetype_reporter.e @@ -259,6 +259,7 @@ feature {NONE} -- Implementation do conv := fac.smart_serialization conv.set_pretty_printing + conv.context.serializer_context.set_is_type_name_included (False) if attached conv.to_json_string (rpt.output_tree) as s then fd.put_string (s) diff --git a/components/adl_compiler/src/interface/report_data_group.e b/components/adl_compiler/src/interface/report_data_group.e index 1831b77bc..59168ef06 100644 --- a/components/adl_compiler/src/interface/report_data_group.e +++ b/components/adl_compiler/src/interface/report_data_group.e @@ -30,6 +30,13 @@ feature -- Access items: HASH_TABLE [REPORT_DATA, STRING] +feature -- Status Report + + is_empty: BOOLEAN + do + Result := attributes.is_empty and items.is_empty + end + feature-- Modification add_item (an_item: REPORT_DATA) diff --git a/components/adl_compiler/src/interface/report_data_node.e b/components/adl_compiler/src/interface/report_data_node.e index dc30d49d0..fe7910538 100644 --- a/components/adl_compiler/src/interface/report_data_node.e +++ b/components/adl_compiler/src/interface/report_data_node.e @@ -18,6 +18,10 @@ inherit create default_create, make +feature -- Definitions + + default_attr_name: STRING = "other" + feature -- Initialisation default_create @@ -28,13 +32,26 @@ feature -- Initialisation feature -- Access - attributes: HASH_TABLE [STRING, STRING] + attributes: HASH_TABLE [HASH_TABLE [STRING, STRING], STRING] feature-- Modification add_attribute (an_item, a_key: STRING) do - attributes.put (an_item, a_key) + add_named_attribute (an_item, a_key, default_attr_name) + end + + add_named_attribute (an_item, a_key, attr_name: STRING) + local + attrs_for_name: HASH_TABLE [STRING, STRING] + do + if attributes.has (attr_name) and then attached attributes.item (attr_name) as ht then + attrs_for_name := ht + else + create attrs_for_name.make (0) + attributes.put (attrs_for_name, attr_name) + end + attrs_for_name.put (an_item, a_key) end end diff --git a/components/adl_compiler/src/interface/value_sets_report.e b/components/adl_compiler/src/interface/value_sets_report.e index 0947beb5d..beac7db93 100644 --- a/components/adl_compiler/src/interface/value_sets_report.e +++ b/components/adl_compiler/src/interface/value_sets_report.e @@ -97,19 +97,26 @@ feature {ARCHETYPE_REPORTER} -- Processing create arch_report.make (auth_ara.id.as_string) - across terminology.value_sets as vset_csr loop - create vset_obj.make (vset_csr.key) - add_term_def (vset_obj, vset_csr.key) + -- add each ac-code + across terminology.value_set_codes as vset_codes_csr loop + create vset_obj.make (vset_codes_csr.item) + add_term_def (vset_obj, vset_codes_csr.item) + + add_bindings (vset_obj, terminology.term_bindings_for_key (vset_codes_csr.item)) + arch_report.add_item (vset_obj) - across vset_csr.item.members as vset_term_code_csr loop - create vset_term_obj.make (vset_term_code_csr.item) - vset_obj.add_item (vset_term_obj) - add_term_def (vset_term_obj, vset_term_code_csr.item) + -- add internal value-set def + if terminology.has_value_set (vset_codes_csr.item) and attached terminology.value_sets.item (vset_codes_csr.item) as vs then + across vs.members as vset_term_code_csr loop + create vset_term_obj.make (vset_term_code_csr.item) + vset_obj.add_item (vset_term_obj) + add_term_def (vset_term_obj, vset_term_code_csr.item) + end end end - if not arch_report.items.is_empty then + if not arch_report.is_empty then output_tree.add_item (arch_report) end end @@ -117,8 +124,15 @@ feature {ARCHETYPE_REPORTER} -- Processing add_term_def (vset_term_obj: REPORT_DATA_NODE; a_term_code: STRING) do - vset_term_obj.add_attribute (terminology.term_definition (default_language, a_term_code).text, "text") - vset_term_obj.add_attribute (terminology.term_definition (default_language, a_term_code).description, "description") + vset_term_obj.add_named_attribute (terminology.term_definition (default_language, a_term_code).text, "text", "definition") + vset_term_obj.add_named_attribute (terminology.term_definition (default_language, a_term_code).description, "description", "definition") + end + + add_bindings (vset_term_obj: REPORT_DATA_NODE; a_bindings: HASH_TABLE [URI, STRING]) + do + across a_bindings as binding_csr loop + vset_term_obj.add_named_attribute (binding_csr.item.as_string, binding_csr.key, "term_bindings") + end end terminology: ARCHETYPE_TERMINOLOGY diff --git a/components/archetype_repository/src/library/archetype_library.e b/components/archetype_repository/src/library/archetype_library.e index 07e11f8f2..501189a4e 100755 --- a/components/archetype_repository/src/library/archetype_library.e +++ b/components/archetype_repository/src/library/archetype_library.e @@ -690,7 +690,7 @@ feature -- Statistical Report Result := compile_attempt_count = archetype_count end - statistics: HASH_TABLE [ARCHETYPE_STATISTICAL_REPORT, STRING] + archetype_statistics: HASH_TABLE [ARCHETYPE_STATISTICAL_REPORT, STRING] -- table of aggregated stats, keyed by BMM_SCHEMA id to which the contributing archetypes relate -- (a single archetype library can contain archetypes of multiple RMs) require @@ -699,10 +699,10 @@ feature -- Statistical Report if compile_activity_timestamp > last_statistics_build_timestamp then build_statistics end - Result := statistics_cache + Result := archetype_statistics_cache end - metrics: HASH_TABLE [INTEGER, STRING] + compilation_statistics: HASH_TABLE [INTEGER, STRING] -- set of key/value pairs, with keys from `Library_metric_names' -- populated by call to `build_statistics' require @@ -711,7 +711,7 @@ feature -- Statistical Report if compile_activity_timestamp > last_statistics_build_timestamp then build_statistics end - Result := metrics_cache + Result := compilation_statistics_cache end terminology_bindings_statistics: HASH_TABLE [ARRAYED_LIST [STRING], STRING] @@ -728,13 +728,13 @@ feature -- Statistical Report feature {NONE} -- Statistical Report - statistics_cache: HASH_TABLE [ARCHETYPE_STATISTICAL_REPORT, STRING] + archetype_statistics_cache: HASH_TABLE [ARCHETYPE_STATISTICAL_REPORT, STRING] -- statistics reports keyed by RM schema id attribute create Result.make (0) end - metrics_cache: HASH_TABLE [INTEGER, STRING] + compilation_statistics_cache: HASH_TABLE [INTEGER, STRING] -- overall metrics, keyed by metric category attribute create Result.make (0) @@ -748,13 +748,13 @@ feature {NONE} -- Statistical Report end build_statistics - -- perform new build of `statistics' and `metrics' + -- perform new build of `archetype_statistics' and `compilation_statistics' require can_build_statistics do reset_statistics do_all_archetypes (agent gather_statistics) - metrics_cache.put (archetype_count, Total_archetype_count) + compilation_statistics_cache.put (archetype_count, Total_archetype_count) create last_statistics_build_timestamp.make_now end @@ -762,12 +762,12 @@ feature {NONE} -- Statistical Report -- Reset counters to zero. do create terminology_bindings_statistics_cache.make (0) - create statistics_cache.make (0) - create metrics_cache.make (Library_metric_names.count) + create archetype_statistics_cache.make (0) + create compilation_statistics_cache.make (Library_metric_names.count) Library_metric_names.do_all ( agent (metric_name: READABLE_STRING_8) do - metrics_cache.put (0, metric_name) + compilation_statistics_cache.put (0, metric_name) end ) create last_statistics_build_timestamp.make_from_epoch (0) @@ -779,18 +779,18 @@ feature {NONE} -- Statistical Report stats: ARRAYED_LIST[STRING] do if aca.is_specialised then - metrics_cache.force (metrics_cache.item (specialised_archetype_count) + 1, specialised_archetype_count) + compilation_statistics_cache.force (compilation_statistics_cache.item (specialised_archetype_count) + 1, specialised_archetype_count) end if aca.differential_has_slots then - metrics_cache.force (metrics_cache.item (client_archetype_count) + 1, client_archetype_count) + compilation_statistics_cache.force (compilation_statistics_cache.item (client_archetype_count) + 1, client_archetype_count) end if aca.is_supplier then - metrics_cache.force (metrics_cache.item (supplier_archetype_count) + 1, supplier_archetype_count) + compilation_statistics_cache.force (compilation_statistics_cache.item (supplier_archetype_count) + 1, supplier_archetype_count) end -- RM stats if aca.is_valid then - metrics_cache.force (metrics_cache.item (valid_archetype_count) + 1, valid_archetype_count) + compilation_statistics_cache.force (compilation_statistics_cache.item (valid_archetype_count) + 1, valid_archetype_count) across aca.safe_differential_archetype.terminology.terminologies_available as terminologies_csr loop if attached terminology_bindings_statistics_cache.item (terminologies_csr.item) as att_stats then stats := att_stats @@ -803,10 +803,10 @@ feature {NONE} -- Statistical Report aca.generate_statistics (True) if attached aca.statistical_analyser as att_sa then - if attached statistics_cache.item (aca.ref_model.model_id) as att_item then + if attached archetype_statistics_cache.item (aca.ref_model.model_id) as att_item then att_item.merge (att_sa.stats) else - statistics_cache.put (att_sa.stats.duplicate, aca.ref_model.model_id) + archetype_statistics_cache.put (att_sa.stats.duplicate, aca.ref_model.model_id) end end end diff --git a/components/archetype_repository/src/library/archetype_library_statistics.e b/components/archetype_repository/src/library/archetype_library_statistics.e new file mode 100644 index 000000000..6b2b6b0b1 --- /dev/null +++ b/components/archetype_repository/src/library/archetype_library_statistics.e @@ -0,0 +1,41 @@ +note + component: "openEHR ADL Tools" + description: "Archetype report data object" + keywords: "export, archetype, ADL" + author: "Thomas Beale " + support: "openEHR AWB project " + copyright: "Copyright (c) 2024 Graphite Health" + license: "Apache 2.0 License " + +class ARCHETYPE_LIBRARY_STATISTICS + +create + make + +feature -- Initialisation + + make (a_library_name, a_component_name: STRING) + do + library_name := a_library_name + component_name := a_component_name + create model_statistics.make (0) + end + +feature -- Access + + library_name: STRING + + component_name: STRING + + model_statistics: HASH_TABLE [REPORTED_STATISTICAL_DATUM, STRING] + +feature -- Modification + + add_model_statistics (a_stats: HASH_TABLE [STATISTICAL_DATUM, STRING]) + do + across a_stats as stats_csr loop + model_statistics.put (stats_csr.item.as_report_item, stats_csr.key) + end + end + +end diff --git a/components/archetype_repository/src/statistics/archetype_statistical_analyser.e b/components/archetype_repository/src/statistics/archetype_statistical_analyser.e index 78836faa3..6dec3ae1b 100755 --- a/components/archetype_repository/src/statistics/archetype_statistical_analyser.e +++ b/components/archetype_repository/src/statistics/archetype_statistical_analyser.e @@ -73,7 +73,9 @@ feature -- Commands if not target.terminology.term_bindings.is_empty then across target.terminology.term_bindings as bindings_for_terminology_csr loop across bindings_for_terminology_csr.item as bindings_list loop - if is_value_set_code (bindings_list.key) then + if is_id_code (bindings_list.key) then + stats.increment_archetype_metric (1, Id_code_bindings_count) + elseif is_value_set_code (bindings_list.key) then stats.increment_archetype_metric (1, Ac_code_bindings_count) else stats.increment_archetype_metric (1, At_code_bindings_count) @@ -90,9 +92,9 @@ feature -- Commands create def_it.make (target.definition) def_it.do_all (agent node_enter, agent node_exit) - stats.archetype_metrics_item (Object_node_count).update (total_node_count) stats.archetype_metrics_item (Archetypable_node_count).update (locatable_node_count) stats.archetype_metrics_item (Archetype_data_value_node_count).update (data_value_node_count) + stats.archetype_metrics_item (Object_node_count).update (total_node_count) end feature {NONE} -- Implementation @@ -107,7 +109,7 @@ feature {NONE} -- Implementation node_enter (a_c_node: ARCHETYPE_CONSTRAINT; depth: INTEGER) local stat_accums: ARRAYED_LIST [RM_CLASS_STATISTICS] - a_class_stat_accum, an_attr_stat_accum: RM_CLASS_STATISTICS + class_stat_accum, attr_stat_accum: RM_CLASS_STATISTICS apa: ARCHETYPE_PATH_ANALYSER ca, ca_parent_flat: C_ATTRIBUTE path_in_flat: STRING @@ -132,13 +134,13 @@ feature {NONE} -- Implementation -- capture node specific info create stat_accums.make (0) - create a_class_stat_accum.make (co.rm_type_name, co.is_root) - stat_accums.extend (a_class_stat_accum) + create class_stat_accum.make (co.rm_type_name, co.is_root) + stat_accums.extend (class_stat_accum) if attached {C_COMPLEX_OBJECT} co as cco then across cco.attributes as attrs_csr loop ca := attrs_csr.item if not ca.has_differential_path then - a_class_stat_accum.add_rm_attribute_occurrence (ca.rm_attribute_name) + class_stat_accum.add_rm_attribute_occurrence (ca.rm_attribute_name) elseif attached flat_parent as att_flat_parent then -- this is the case of constraint at a path, as found in specialised archetypes - -- it is an attribute for a different RM object type @@ -156,13 +158,13 @@ feature {NONE} -- Implementation co_type_name := bmm_class_def.name is_root_flag := False end - create an_attr_stat_accum.make (co_type_name, is_root_flag) - an_attr_stat_accum.add_rm_attribute_occurrence (ca.rm_attribute_name) - stat_accums.extend (an_attr_stat_accum) + create attr_stat_accum.make (co_type_name, is_root_flag) + attr_stat_accum.add_rm_attribute_occurrence (ca.rm_attribute_name) + stat_accums.extend (attr_stat_accum) end end elseif attached {C_DOMAIN_TYPE} co as cdt then - a_class_stat_accum.add_rm_attribute_occurrences (cdt.constrained_rm_attributes) + class_stat_accum.add_rm_attribute_occurrences (cdt.constrained_rm_attributes) end stat_accums.do_all (agent (a_stat_accum: RM_CLASS_STATISTICS) do stats.add_rm_class_stats (a_stat_accum) end) end diff --git a/components/archetype_repository/src/statistics/archetype_statistical_definitions.e b/components/archetype_repository/src/statistics/archetype_statistical_definitions.e index 5a497a968..bc7b01e37 100755 --- a/components/archetype_repository/src/statistics/archetype_statistical_definitions.e +++ b/components/archetype_repository/src/statistics/archetype_statistical_definitions.e @@ -53,9 +53,9 @@ feature -- Definitions Result := get_text (ec_arch_stats_ac_codes_text) end - At_code_bindings_count: READABLE_STRING_8 + Id_code_bindings_count: READABLE_STRING_8 once - Result := get_text (ec_arch_stats_at_code_bindings_text) + Result := get_text (ec_arch_stats_id_code_bindings_text) end Ac_code_bindings_count: READABLE_STRING_8 @@ -63,18 +63,24 @@ feature -- Definitions Result := get_text (ec_arch_stats_ac_code_bindings_text) end + At_code_bindings_count: READABLE_STRING_8 + once + Result := get_text (ec_arch_stats_at_code_bindings_text) + end + Archetype_metric_names: ARRAYED_LIST [READABLE_STRING_8] once create Result.make (0) Result.compare_objects - Result.extend (Object_node_count) Result.extend (Archetypable_node_count) Result.extend (Archetype_data_value_node_count) Result.extend (Id_code_count) - Result.extend (At_code_count) Result.extend (Ac_code_count) - Result.extend (At_code_bindings_count) + Result.extend (At_code_count) + Result.extend (Id_code_bindings_count) Result.extend (Ac_code_bindings_count) + Result.extend (At_code_bindings_count) + Result.extend (Object_node_count) end Total_archetype_count: READABLE_STRING_8 diff --git a/components/archetype_repository/src/statistics/reported_statistical_datum.e b/components/archetype_repository/src/statistics/reported_statistical_datum.e new file mode 100644 index 000000000..581132b2f --- /dev/null +++ b/components/archetype_repository/src/statistics/reported_statistical_datum.e @@ -0,0 +1,44 @@ +note + component: "openEHR ADL Tools" + description: "Extracted form of STATISTICAL_DATUM, suitable for including in report object" + keywords: "statistics, archetype" + author: "Thomas Beale " + support: "http://www.openehr.org/issues/browse/AWB" + copyright: "Copyright (c) 2011 Ocean Informatics Pty Ltd " + license: "Apache 2.0 License " + +class REPORTED_STATISTICAL_DATUM + +create + make + +feature -- Initialisation + + make (a_name: STRING; a_total, a_min, a_max: INTEGER; an_ave: REAL) + do + name := a_name + total := a_total + minimum := a_min + maximum := a_max + average := an_ave + end + +feature -- Access + + name: STRING + -- name of this datum + + total: INTEGER + -- total number of occurrences of this datum across the population + + minimum: INTEGER + -- minimum non-zero number of occurrences of this datum across the population + + maximum: INTEGER + -- maximum number of occurrences of this datum across the population + + average: REAL + +end + + diff --git a/components/archetype_repository/src/statistics/statistical_datum.e b/components/archetype_repository/src/statistics/statistical_datum.e index 58f8ba11e..29291ef69 100755 --- a/components/archetype_repository/src/statistics/statistical_datum.e +++ b/components/archetype_repository/src/statistics/statistical_datum.e @@ -77,6 +77,13 @@ feature -- Modification maximum := maximum.max (other.maximum) end +feature -- Conversion + + as_report_item: REPORTED_STATISTICAL_DATUM + do + create Result.make (name, total, minimum, maximum, average) + end + end