Skip to content

Commit

Permalink
initial skeleton for NeXus App (#474)
Browse files Browse the repository at this point in the history
* initial skeleton for NeXus App

* a minimalistic App

* fix merge

* comments added as suggested in code review
  • Loading branch information
sanbrock authored Dec 3, 2024
1 parent d52934c commit cf4b792
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 4 deletions.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
127 changes: 126 additions & 1 deletion src/pynxtools/nomad/entrypoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
#
try:
from nomad.config.models.plugins import (
AppEntryPoint,
ExampleUploadEntryPoint,
ParserEntryPoint,
SchemaPackageEntryPoint,
ExampleUploadEntryPoint,
)
except ImportError as exc:
raise ImportError(
Expand Down Expand Up @@ -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",
Expand Down
8 changes: 5 additions & 3 deletions src/pynxtools/nomad/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)

Expand All @@ -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


Expand Down Expand Up @@ -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('')
Expand All @@ -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()
Expand Down

0 comments on commit cf4b792

Please sign in to comment.