{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Model Analysis Demo with IncQuery Server Jupyter Client Extensions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Preliminaries" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Setup IQS Connection" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Execute the following piece of code to connect to the public IncQuery Server demo instance.\n", "\n", "If you have non-guest privileges, you may specify your credentials here." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "import iqs_jupyter\n", "iqs = iqs_jupyter.connect(\n", " address='https://openmbee.incquery.io',\n", " user='guest',\n", " password='incqueryserverguest'\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Select MMS commit to consider" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Run the next code block to display the commit selector widget, and use it to browse around the MMS repository. When you've had your fun, make sure to leave it in a state where a commit is selected from the _IQS4MMS Demos_ org, as we have made sure to pre-index and load those commits in the IQS." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "commit_selector = iqs.jupyter_tools.mms_commit_selector_widget()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following piece of code assigns the Python name `model` to the MMS commit selected above, and checks whether the model is indeed indexed and loaded by IQS, which is required for the rest of the demo " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "model = commit_selector.value().to_model_compartment()\n", "if model.is_loaded_by_server(iqs):\n", " print(\"We may proceed.\")\n", "else: \n", " print(\"Model is not indexed&loaded by IQS, so the next demo steps will not work.\")\n", " print(\" (Unfortunately, guest users are not allowed to control model indexing.)\")\n", " print(\"Please select another model from the 'IQS4MMS Demos' org.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Define and register reproducible analysis configuration" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Query definition and registration" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, we define and register a **Viatra** graph query for computing requirements traceability coverage." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "coverage_query_package = \"iqs4mms.demo.coverage\"\n", "coverage_query_main = \"iqs4mms.demo.coverage.packageCoverage\"\n", "coverage_query_code = '''\n", "\n", "// SECTION 1: main query\n", "\n", "/* \n", " * Associates a UML package with \n", " * - the total number of transitively contained SysML Blocks, and \n", " * - the number of strongly and weakly covered blocks among them\n", " */\n", "incremental pattern packageCoverage(\n", " pack: Package, \n", " totalBlocks: java Integer, \n", " stronglyCovered: java Integer, \n", " weaklyCovered: java Integer\n", ") {\n", " totalBlocks == count find blockInPackage(_, pack);\n", " stronglyCovered == count find stronglyCoveredBlockInPackage(_, pack);\n", " weaklyCovered == count find weaklyCoveredBlockInPackage(_, pack);\n", "}\n", "\n", "\n", "// SECTION 2: custom in-house definitions for strong and weak coverage\n", "\n", "/* \n", " * Identifies elements that are strongly covered by a requirement.\n", " * This definition may be customized according to in-house concept of strong coverage.\n", " */\n", "incremental pattern stronglyCovered(element: NamedElement) {\n", " find sysml.Requirement_SatisfiedBy(_, element);\n", "} or {\n", " find sysml.Requirement_VerifiedBy(_, element);\n", "} or {\n", " find sysml.Requirement_TracedTo(_, element);\n", "}\n", "/* \n", " * Identifies elements that are NOT strongly covered, \n", " * but are reachable from a strongly covered element \n", " * using one or more custom propagation steps\n", " */\n", "incremental pattern weaklyCovered(element: NamedElement) {\n", " find stronglyCovered(otherElement);\n", " find coveragePropagates+(otherElement, element);\n", " neg find stronglyCovered(element);\n", "}\n", "/* \n", " * Defines custom coverage propagation steps, where \n", " * coverage of a 'from' element automatically implies weak coverage of a 'to' element.\n", " * This definition may be customized according to in-house propagation rules.\n", " */\n", "incremental pattern coveragePropagates(from: NamedElement, to: NamedElement) {\n", " // from container to contained part\n", " Property.owner(part, from);\n", " Property.aggregation(part, ::composite);\n", " TypedElement.type(part, to);\n", "} or { \n", " // from general superclassifier / block to specific block\n", " Generalization.general(gen, from);\n", " Generalization.specific(gen, to);\n", "}\n", "\n", "// SECTION 3: helper queries to assemble a report on (transitive) package contents\n", "\n", "/* \n", " * Associates SysML Blocks with UML packages directly or indirectly containing them.\n", " */\n", "incremental pattern blockInPackage(block: Class, pack: Package) {\n", " find sysml.Block(block, _); \n", " Element.owner+(block, pack);\n", "}\n", "/* \n", " * Associates strongly covered Blocks with UML packages directly or indirectly containing them.\n", " */\n", "incremental pattern stronglyCoveredBlockInPackage(block: Class, pack: Package) {\n", " find stronglyCovered(block); \n", " find blockInPackage(block, pack);\n", "}\n", "/* \n", " * Associates weakly covered Blocks with UML packages directly or indirectly containing them.\n", " */\n", "incremental pattern weaklyCoveredBlockInPackage(block: Class, pack: Package) {\n", " find weaklyCovered(block); \n", " find blockInPackage(block, pack);\n", "}\n", "\n", "\n", "'''" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "code_folding": [], "scrolled": false }, "outputs": [], "source": [ "from iqs_jupyter import schema\n", "if coverage_query_main not in iqs.queries.list_queries().viatra.query_fq_ns: # skip if already registered\n", " try: \n", " iqs.queries.register_queries_plain_text(coverage_query_code, query_package=coverage_query_package)\n", " display(iqs.query_execution.prepare_standing_queries_on_model_compartment(\n", " schema.QueryFQNListWithModelCompartment(\n", " model_compartment = model,\n", " query_fq_ns = [coverage_query_main]\n", " )))\n", " except: \n", " print(\"Query registration not available as guest user; please try again in a few minutes\")\n", "else:\n", " print(\"Query is already registered; proceed\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we define and register a **Lucene** full-text query for finding text notes that suggest incompleteness." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "todos_query_package = \"iqs.lucene.example\"\n", "todos_query_simplename = \"todo\"\n", "todos_query_code = 'todo\\ntbd\\nmissing\\nincomplete'\n", "todos_query_fqn = \"{}.{}\".format(todos_query_package, todos_query_simplename)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if todos_query_fqn not in iqs.queries.list_queries().lucene.query_fq_ns: # skip if already registered\n", " try: \n", " display(iqs.queries.register_queries(schema.QueryDefinitionRequest(\n", " query_definitions = [todos_query_code], \n", " package_name = todos_query_package,\n", " query_name = todos_query_simplename,\n", " query_language = 'lucene'\n", " )))\n", " except: \n", " print(\"Query registration not available as guest user; please try again in a few minutes\")\n", "else:\n", " print(\"Query is already registered; proceed\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, we define and register a **SPARQL** graph query that selects named elements with too short names. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "shortname_query_package = \"iqs4mms.demo.sparql\"\n", "shortname_query_simplename = \"nameTooShort\"\n", "shortname_query_code = '''\n", "select ?c ?n where { \n", " ?c rdf:type/rdfs:subClassOf* uml:NamedElement .\n", " ?c uml:NamedElement.name ?n .\n", " FILTER(0 < STRLEN(?n) && STRLEN(?n) < 5)\n", "}\n", "'''\n", "shortname_query_fqn = \"{}.{}\".format(shortname_query_package, shortname_query_simplename)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if shortname_query_fqn not in iqs.queries.list_queries().sparql.query_fq_ns: # skip if already registered\n", " try: \n", " iqs.queries.register_queries(schema.QueryDefinitionRequest(\n", " query_definitions = [shortname_query_code], \n", " package_name = shortname_query_package,\n", " query_name = shortname_query_simplename,\n", " query_language = 'sparql'\n", " ))\n", " except: \n", " print(\"Query registration not available as guest user; please try again in a few minutes\")\n", "else:\n", " print(\"Query is already registered; proceed\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Define reproducible analysis" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from iqs_jupyter import schema\n", "analysis_config_name = \"My first analysis configuration with IncQuery Model Analysis Suite\"\n", "analysis_config = schema.AnalysisConfiguration(\n", " name = analysis_config_name,\n", " configuration_rules = [\n", " schema.AnalysisRule(\n", " name = \"Block coverage ratios per package\", \n", " query_fqn = coverage_query_main,\n", " severity = \"INFO\",\n", " message_template = \"Coverage of block\"\n", " ),\n", " schema.AnalysisRule(\n", " name = \"Text occurrences of 'TODO'/'TBD'/'MISSING'/'INCOMPLETE'\", \n", " query_fqn = todos_query_fqn,\n", " severity = \"INFO\",\n", " message_template = \"Review this item\"\n", " ),\n", " schema.AnalysisRule(\n", " name = \"Elements with very short name\", \n", " query_fqn = shortname_query_fqn,\n", " severity = \"WARNING\",\n", " message_template = \"Element has a very short name (is it abbreviated?)\"\n", " )\n", " ]\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "configs_with_given_name = [ config \n", " for config in iqs.analysis.list_model_analysis_configurations().model_analysis_configuration_identifiers\n", " if config.configuration_name == analysis_config_name\n", "]\n", "if configs_with_given_name: # found analysis pre-registered\n", " analysis_config = configs_with_given_name[0]\n", " print (\"Analysis configuration '{}' found. \\nGo on.\".format(analysis_config_name))\n", "else: # not found \n", " try:\n", " iqs.analysis.register_model_analysis_configuration(analysis_configuration = analysis_config)\n", " except:\n", " print (\"Error: analysis configuration '{}' not found, must be pre-registered for this demo\".format(analysis_config_name))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Use reproducible model analysis" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Find pre-registered model analysis" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "analysis_config_name = \"My first analysis configuration with IncQuery Model Analysis Suite\"\n", "configs_with_given_name = [ config \n", " for config in iqs.analysis.list_model_analysis_configurations().model_analysis_configuration_identifiers\n", " if config.configuration_name == analysis_config_name\n", "]\n", "if configs_with_given_name:\n", " analysis_config = configs_with_given_name[0]\n", " print (\"Analysis configuration '{}' found. \\nGo on.\".format(analysis_config_name))\n", "else:\n", " print (\"Error: analysis configuration '{}' not found, must be pre-registered for this demo\".format(analysis_config_name))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Execute analysis configuration on selected model" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "from iqs_jupyter import schema\n", "analysis_execution_response = iqs.analysis.run_model_analysis(analysis_execution_request = schema.AnalysisExecutionRequest(\n", " configuration_id = analysis_config.configuration_id,\n", " compartment = model\n", "))\n", "analysis_execution_response" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Upload analysis results via direct MMS connection" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, connect to the MMS server." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import iqs_jupyter # if not already imported\n", "mms = iqs_jupyter.MMSClient(\n", " address = \"https://mms.openmbee.org/alfresco/service\",\n", " user = \"openmbeeguest\",\n", " password= \"guest\"\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Below we export an HTML report from the analysis results. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "analysis_report_html = '''\n", "

Model Analysis Report

\n", "{}\n", "'''.format(\n", " analysis_execution_response._repr_html_()\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The generated HTML report can be directly uploaded to MMS. Here we are uploading it to a sandbox document that is publicly writeable." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "target_project = 'PROJECT-3cc8325d-f955-424f-8410-4dcdbcae621e'\n", "target_ref = 'master'\n", "target_element = '_hidden_MMS_1575975609494_b5ca9eb4-6db2-41d7-8b93-db9897def885_pei'\n", "mms.element.post_elements(target_project, target_ref,{\"elements\": [\n", " {\"id\": target_element, \"documentation\": analysis_report_html}\n", "]})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The uploaded report is available at [MMS (IQMAS-Jupyter-Example)](https://mms.openmbee.org/alfresco/mmsapp/mms.html#/projects/PROJECT-3cc8325d-f955-424f-8410-4dcdbcae621e/master/documents/MMS_1575971237988_af1e9d00-3c99-4098-9726-3144d02b1d66/views/MMS_1575971237988_af1e9d00-3c99-4098-9726-3144d02b1d66)." ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true }, "source": [ "### Sandbox" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Extra section for privileged users\n", "Do not forget to specify your privileged credentials at the top of the notebook, in the first code cell" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true }, "source": [ "### Repository management, indexing commits" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "Force the server to refresh its knowledge of commits in the repository:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "code_folding": [], "hidden": true, "scrolled": true }, "outputs": [], "source": [ "iqs.mms_repository.update_mms_repository()" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "Index another model from the repository, and then load the index into server memory:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "iqs.persistent_index.index_model_compartment(model)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true, "scrolled": true }, "outputs": [], "source": [ "iqs.in_memory_index.load_model_compartment(model)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true, "scrolled": false }, "outputs": [], "source": [ "iqs.integration.elastic_search_load_model_compartment(model)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "model_in_rdf = schema.ModelCompartmentWithModelFormat(\n", " model_compartment = model,\n", " format = \"RDF_TURTLE\"\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "iqs.persistent_index.transform_model_compartment(model_in_rdf)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "iqs.integration.aws_s3_publish_model_compartment(model_in_rdf)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "iqs.integration.aws_neptune_load_model_compartment(model_in_rdf)" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true }, "source": [ "### Cleaning up query and analysis definitions" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "iqs.queries.unregister_all_queries()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "analysis_config_name = \"My first analysis configuration with IncQuery Model Analysis Suite\"\n", "for config in (\n", " config\n", " for config in iqs.analysis.list_model_analysis_configurations().model_analysis_configuration_identifiers\n", " if config.configuration_name == analysis_config_name\n", "):\n", " iqs.analysis.delete_model_analysis_configuration(analysis_configuration_identifier = config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Sandbox" ] }, { "cell_type": "markdown", "metadata": {}, "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": { "211e3fc98297499e99515b3410e9f734": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "2ddc34746d7349e5ab4fba57cfa690f1": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "DropdownModel", "state": { "_options_labels": [ "---- Select commit", "2019-06-24 11:48:57 (ID: 0e4c90e2-ee9d-4d7e-9d90-e7fb7bb2c0c8)", "2019-06-24 10:57:54 (ID: 51f09858-5337-4cdd-90bd-027120bd39e7)", "2019-06-12 14:56:28 (ID: 8598d33b-4950-4355-a404-18b0d8148b47)" ], "index": 1, "layout": "IPY_MODEL_b8a2cde3502448a6ae52b3b558de2a12", "style": "IPY_MODEL_5684d3550b7b4e009ed925f42a32c18b" } }, "3b082fd4deeb492c9c3ba4b8f445e919": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "423b2ae9cc04448e8c6b90dadaef2914": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "479c03d03b8f42e7a281ac66e731a879": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "LabelModel", "state": { "layout": "IPY_MODEL_211e3fc98297499e99515b3410e9f734", "style": "IPY_MODEL_ab1cc7ba3b5f444989a8eb280126f28c", "value": "project" } }, "480f2e2c3d8644d39ac000bd8263e927": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "5684d3550b7b4e009ed925f42a32c18b": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "DescriptionStyleModel", "state": { "description_width": "" } }, "7000f47850794659af668aabbf3a9b71": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "DescriptionStyleModel", "state": { "description_width": "" } }, "75590ca4b04e43a291c04c401aae1ddd": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "760cf62c32fb41959c9094cd911fb7d6": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "DropdownModel", "state": { "_options_labels": [ "---- Select org", "IQS4MMS Demos (ID: 9ff6af30-af8a-4f9d-a26b-499010ba5b6e)" ], "index": 1, "layout": "IPY_MODEL_cc794bf07298416b9c940e1c0303c69a", "style": "IPY_MODEL_7c60de6dbd54446ea28f39fbcabf8db2" } }, "7c60de6dbd54446ea28f39fbcabf8db2": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "DescriptionStyleModel", "state": { "description_width": "" } }, "7dd0722722514e10aacbdcf91efed66d": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "DescriptionStyleModel", "state": { "description_width": "" } }, "8071fff5b2cb4f62bec8ceea9ad645fa": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "DropdownModel", "state": { "_options_labels": [ "---- Select project", "Validation_UML_Example (ID: PROJECT-d0c236d9-186a-485c-9c67-9e6693d1f0d8)", "TMT (ID: PROJECT-0e791c0e-16fe-422f-8f85-462ab035ce99)" ], "index": 2, "layout": "IPY_MODEL_480f2e2c3d8644d39ac000bd8263e927", "style": "IPY_MODEL_ca0040032a8e4676bc84ff3a033e47d5" } }, "87658b4a59e14b9fb5380e328a61a84f": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "888b0c5135174809a355381311ba4ec7": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "LabelModel", "state": { "layout": "IPY_MODEL_87658b4a59e14b9fb5380e328a61a84f", "style": "IPY_MODEL_d394bc289e1741a1a28608bd520b3f46", "value": "commit" } }, "a30a6e3f93ab4b7f97496f6c01daf3ee": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "VBoxModel", "state": { "children": [ "IPY_MODEL_e09fa0e9b6ae47f194c83d5aaf559749", "IPY_MODEL_479c03d03b8f42e7a281ac66e731a879", "IPY_MODEL_f1f8ac15e67941bc98918a7d4e846601", "IPY_MODEL_888b0c5135174809a355381311ba4ec7" ], "layout": "IPY_MODEL_75590ca4b04e43a291c04c401aae1ddd" } }, "ab1cc7ba3b5f444989a8eb280126f28c": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "DescriptionStyleModel", "state": { "description_width": "" } }, "b7102a2d93294e058ad34be52bf6cedd": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "DescriptionStyleModel", "state": { "description_width": "" } }, "b8a2cde3502448a6ae52b3b558de2a12": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "c869ef979c204831ba2d4cb306c80ed0": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "c913303482ea4ed58f4441227d00ed7c": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "ca0040032a8e4676bc84ff3a033e47d5": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "DescriptionStyleModel", "state": { "description_width": "" } }, "cc794bf07298416b9c940e1c0303c69a": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "cd307892b2904e69b4255c5b48c422c2": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "VBoxModel", "state": { "children": [ "IPY_MODEL_760cf62c32fb41959c9094cd911fb7d6", "IPY_MODEL_8071fff5b2cb4f62bec8ceea9ad645fa", "IPY_MODEL_ff65a8c7bc384983932833d99d0a47f6", "IPY_MODEL_2ddc34746d7349e5ab4fba57cfa690f1" ], "layout": "IPY_MODEL_c913303482ea4ed58f4441227d00ed7c" } }, "d394bc289e1741a1a28608bd520b3f46": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "DescriptionStyleModel", "state": { "description_width": "" } }, "dd4d44c82e804f7899685472e7e17650": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "e09fa0e9b6ae47f194c83d5aaf559749": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "LabelModel", "state": { "layout": "IPY_MODEL_dd4d44c82e804f7899685472e7e17650", "style": "IPY_MODEL_b7102a2d93294e058ad34be52bf6cedd", "value": "org" } }, "f1f8ac15e67941bc98918a7d4e846601": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "LabelModel", "state": { "layout": "IPY_MODEL_3b082fd4deeb492c9c3ba4b8f445e919", "style": "IPY_MODEL_7dd0722722514e10aacbdcf91efed66d", "value": "ref" } }, "fe43ca40e9694b58b872aa47fa6ef78b": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "HBoxModel", "state": { "children": [ "IPY_MODEL_a30a6e3f93ab4b7f97496f6c01daf3ee", "IPY_MODEL_cd307892b2904e69b4255c5b48c422c2" ], "layout": "IPY_MODEL_423b2ae9cc04448e8c6b90dadaef2914" } }, "ff65a8c7bc384983932833d99d0a47f6": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "DropdownModel", "state": { "_options_labels": [ "---- Select ref", "master (ID: master)" ], "index": 1, "layout": "IPY_MODEL_c869ef979c204831ba2d4cb306c80ed0", "style": "IPY_MODEL_7000f47850794659af668aabbf3a9b71" } } }, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 2 }