diff --git a/pyproject.toml b/pyproject.toml index 27ec84f86..6d74932e0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -96,6 +96,7 @@ xrd = [ nexus_parser = "pynxtools.nomad.entrypoints:nexus_parser" nexus_schema = "pynxtools.nomad.entrypoints:nexus_schema" nexus_data_converter = "pynxtools.nomad.entrypoints:nexus_data_converter" +nexus_app = "pynxtools.nomad.entrypoints:nexus_app" iv_temp_example = "pynxtools.nomad.entrypoints:iv_temp_example" [project.scripts] diff --git a/src/pynxtools/nomad/entrypoints.py b/src/pynxtools/nomad/entrypoints.py index 29127dbcd..dfd957a8f 100644 --- a/src/pynxtools/nomad/entrypoints.py +++ b/src/pynxtools/nomad/entrypoints.py @@ -17,9 +17,10 @@ # try: from nomad.config.models.plugins import ( + AppEntryPoint, + ExampleUploadEntryPoint, ParserEntryPoint, SchemaPackageEntryPoint, - ExampleUploadEntryPoint, ) except ImportError as exc: raise ImportError( @@ -65,6 +66,130 @@ def load(self): mainfile_mime_re="application/x-hdf5", ) +from nomad.config.models.ui import ( + App, + Column, + Menu, + MenuItemHistogram, + MenuItemPeriodicTable, + MenuItemTerms, + SearchQuantities, +) + +schema = "pynxtools.nomad.schema.NeXus" + +nexus_app = AppEntryPoint( + name="NexusApp", + description="Simple Generic NeXus app.", + app=App( + # Label of the App + label="NeXus", + # Path used in the URL, must be unique + path="nexusapp", + # Used to categorize apps in the explore menu + category="Experiment", + # Brief description used in the app menu + description="A simple search app customized for generic NeXus data.", + # Longer description that can also use markdown + readme="This is a simple App to support basic search for NeXus based Experiment Entries.", + # If you want to use quantities from a custom schema, you need to load + # the search quantities from it first here. Note that you can use a glob + # syntax to load the entire package, or just a single schema from a + # package. + search_quantities=SearchQuantities( + include=[f"*#{schema}"], + ), + # Controls which columns are shown in the results table + columns=[ + Column(quantity="entry_id", selected=True), + Column(quantity=f"entry_type", selected=True), + Column( + title="definition", + quantity=f"data.*.ENTRY[*].definition__field#{schema}", + selected=True, + ), + Column( + title="start_time", + quantity=f"data.*.ENTRY[*].start_time__field#{schema}", + selected=True, + ), + Column( + title="title", + quantity=f"data.*.ENTRY[*].title__field#{schema}", + selected=True, + ), + ], + # Dictionary of search filters that are always enabled for queries made + # within this app. This is especially important to narrow down the + # results to the wanted subset. Any available search filter can be + # targeted here. This example makes sure that only entries that use + # MySchema are included. + filters_locked={"section_defs.definition_qualified_name": [schema]}, + # Controls the menu shown on the left + menu=Menu( + title="Material", + items=[ + Menu( + title="elements", + items=[ + MenuItemPeriodicTable( + quantity="results.material.elements", + ), + MenuItemTerms( + quantity="results.material.chemical_formula_hill", + width=6, + options=0, + ), + MenuItemTerms( + quantity="results.material.chemical_formula_iupac", + width=6, + options=0, + ), + MenuItemHistogram( + x="results.material.n_elements", + ), + ], + ) + ], + ), + # Controls the default dashboard shown in the search interface + dashboard={ + "widgets": [ + { + "type": "histogram", + "show_input": False, + "autorange": True, + "nbins": 30, + "scale": "linear", + "quantity": f"data.Root.datetime#{schema}", + "title": "Procesing Time", + "layout": { + "lg": {"minH": 3, "minW": 3, "h": 4, "w": 12, "y": 0, "x": 0} + }, + }, + { + "type": "terms", + "show_input": False, + "scale": "linear", + "quantity": f"entry_type", + "title": "Entry Type", + "layout": { + "lg": {"minH": 3, "minW": 3, "h": 8, "w": 4, "y": 0, "x": 12} + }, + }, + { + "type": "periodic_table", + "scale": "linear", + "quantity": f"results.material.elements", + "layout": { + "lg": {"minH": 3, "minW": 3, "h": 4, "w": 12, "y": 4, "x": 0} + }, + }, + ] + }, + ), +) + iv_temp_example = ExampleUploadEntryPoint( title="Sensor Scan - IV Temperature Curve", category="FAIRmat examples", diff --git a/src/pynxtools/nomad/schema.py b/src/pynxtools/nomad/schema.py index 22818ef15..fbb68bb8d 100644 --- a/src/pynxtools/nomad/schema.py +++ b/src/pynxtools/nomad/schema.py @@ -33,7 +33,7 @@ try: from nomad import utils from nomad.datamodel import EntryArchive, EntryMetadata - from nomad.datamodel.data import EntryData + from nomad.datamodel.data import EntryData, Schema from nomad.datamodel.metainfo.basesections import ( BaseSection, Component, @@ -775,6 +775,7 @@ def __create_package_from_nxdl_directories(nexus_section: Section) -> Package: """ Creates a metainfo package from the given nexus directory. Will generate the respective metainfo definitions from all the nxdl files in that directory. + The parent Schema is also populated with all AppDefs and then is is also added to the package. """ package = Package(name=__PACKAGE_NAME) @@ -799,6 +800,7 @@ def __create_package_from_nxdl_directories(nexus_section: Section) -> Package: SubSection(section_def=section, name=section.name) ) + package.section_definitions.append(nexus_section) return package @@ -832,9 +834,11 @@ def init_nexus_metainfo(): # We take the application definitions and create a common parent section that allows # to include nexus in an EntryArchive. + # To be able to register it into data section, it is expected that this section inherits from Schema. nexus_section = Section( validate=VALIDATE, name=__GROUPING_NAME, label=__GROUPING_NAME ) + nexus_section.base_sections = [Schema.m_def] # try: # load_nexus_schema('') @@ -846,8 +850,6 @@ def init_nexus_metainfo(): # pass nexus_metainfo_package = __create_package_from_nxdl_directories(nexus_section) - nexus_metainfo_package.section_definitions.append(nexus_section) - # We need to initialize the metainfo definitions. This is usually done automatically, # when the metainfo schema is defined though MSection Python classes. nexus_metainfo_package.init_metainfo()