diff --git a/docs/reference/annotations.md b/docs/reference/annotations.md index 0f985c5232dc0596422f068fa3683cf5cecfad5b..621fa7dd75f64b136bf6c9205902428f42884434 100644 --- a/docs/reference/annotations.md +++ b/docs/reference/annotations.md @@ -18,44 +18,11 @@ Many annotations control the representation of data in the GUI. This can be for {{ pydantic_model('nomad.datamodel.metainfo.annotations.BrowserAnnotation', heading='## Browser') }} -{{ pydantic_model('nomad.datamodel.metainfo.annotations.BrowserAnnotation', heading='## browser') }} +## Display annotations -### `display unit system` -The unit system to override the global or the unit system determined by parent. It could be used in the level of Package, Section, or Quantity. -One can use the supported [unit systems](./config.md#unitsystems) such as `SI` or `AU`. +{{ pydantic_model('nomad.datamodel.metainfo.annotations.QuantityDisplayAnnotation', heading='### Display annotation for quantities') }} -```yaml -definitions: - name: 'Sun' - m_annotations: - display: - unit_system: SI - sections: - SolarSystem: - quantities: - total_energy: - type: float - description: The total energy in SI unit system, energy unit - sub_sections: - Electrons: - section: - m_annotations: - display: - unit_system: AU - quantities: - free_energy: - type: float - description: The electron energy in AU unit system, energy unit - energy: - m_annotations: - display: - unit: erg - type: float - description: The electron energy in a custom unit -``` - -### `display unit` -To determine the desired unit to override the global or the unit determined by parent. See the example in [display unit system](#display_unit_system). +{{ pydantic_model('nomad.datamodel.metainfo.annotations.SectionDisplayAnnotation', heading='### Display annotation for sections') }} ### `label_quantity` diff --git a/gui/src/components/archive/ArchiveBrowser.js b/gui/src/components/archive/ArchiveBrowser.js index e76c9668444766807543d248c9b09f305f984949..e33394ef4930d1cd3a8fb388be9c89dd24dca427 100644 --- a/gui/src/components/archive/ArchiveBrowser.js +++ b/gui/src/components/archive/ArchiveBrowser.js @@ -71,6 +71,7 @@ import { useEntryStore } from '../entry/EntryContext' import ArchiveSearchBar from './ArchiveSearchBar' import DOMPurify from 'dompurify' import XYPlot from "./XYPlot" +import { useDisplayUnit } from '../units/useDisplayUnit' export const configState = atom({ key: 'config', @@ -649,7 +650,8 @@ const convertComplexArray = (real, imag) => { } export function QuantityItemPreview({value, def}) { - const {units, unitSystems, isReset} = useUnitContext() + const displayUnit = useDisplayUnit(def) + if (isReference(def)) { return <Box component="span" fontStyle="italic"> <Typography component="span">reference ...</Typography> @@ -707,27 +709,12 @@ export function QuantityItemPreview({value, def}) { finalValue = value } - let finalUnit - if (def.unit) { - let a - const section_default_unit_system = def?._parent?.m_annotations?.display?.[0]?.unit_system - const quantity_default_unit = def?.m_annotations?.display?.[0]?.unit - if (isReset && (section_default_unit_system || quantity_default_unit)) { - if (section_default_unit_system && unitSystems[section_default_unit_system]) { - a = new Q(finalValue, def.unit).toSystem(unitSystems[section_default_unit_system].units) - } - if (quantity_default_unit) { - a = new Q(finalValue, def.unit).to(quantity_default_unit) - } - } else { - a = new Q(finalValue, def.unit).toSystem(units) - } - finalValue = a.value() - finalUnit = a.label() + if (displayUnit) { + finalValue = new Q(finalValue, def.unit).to(displayUnit).value() } return <Box component="span" whiteSpace="nowarp"> <Number component="span" variant="body1" value={finalValue} exp={8}/> - {finalUnit && <Typography component="span"> {finalUnit}</Typography>} + {displayUnit && <Typography component="span"> {displayUnit.label()}</Typography>} </Box> } } @@ -922,7 +909,6 @@ export function Section({section, def, parentRelation, sectionIsEditable, sectio const [showJson, setShowJson] = useState(false) const lane = useContext(laneContext) const history = useHistory() - useUnitContext(def._package.name, def?._package?.m_annotations?.display?.[0]?.unit_system) const isEditable = useMemo(() => { let editableExcluded = false diff --git a/gui/src/components/archive/ArchiveBrowser.spec.js b/gui/src/components/archive/ArchiveBrowser.spec.js index 25552ff37cc05cf9d68d39ad0ae69df4b39bb440..ccb2e447d9c78adf4c7c2753c1710b085480338a 100644 --- a/gui/src/components/archive/ArchiveBrowser.spec.js +++ b/gui/src/components/archive/ArchiveBrowser.spec.js @@ -17,6 +17,7 @@ */ import React from 'react' import { range } from 'lodash' +import { TestAdaptor } from './conftest.spec' import { screen, renderNoAPI, render } from '../conftest.spec' import { expectPagination } from '../visualization/conftest.spec' import { PropertyValuesList, Section } from './ArchiveBrowser' @@ -24,7 +25,6 @@ import { laneContext } from './Browser' import {waitFor} from "@testing-library/dom" import {Metainfo} from './metainfo' import {systemMetainfoUrl} from '../../utils' -import {TestAdaptor} from './Browser.spec' test.each([ [15, 10, 5], diff --git a/gui/src/components/archive/Browser.spec.js b/gui/src/components/archive/Browser.spec.js index 997e5e5bf506c742da55eee56303969eb725e80b..319f5cbf72152eaf46a6a16759e80c94a7370e19 100644 --- a/gui/src/components/archive/Browser.spec.js +++ b/gui/src/components/archive/Browser.spec.js @@ -15,67 +15,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { join, basename } from 'path' import React from 'react' -import PropTypes from 'prop-types' import { waitFor } from '@testing-library/dom' import { blockConsoleOutput, expectNoConsoleOutput, filteredConsoleOutput, consoleSpies, render, screen, within } from '../conftest.spec' -import { itemsInTreePath, checkLanes, navigateTo, selectItemAndWaitForRender, getLane } from './conftest.spec' -import Browser, { Item, Content, Compartment, Adaptor, Title, laneErrorBoundryMessage } from './Browser' - -function checkTestLane({lane, laneIndex, lanePath, lastSegment, browserTree, rootTitle}) { - expect(within(lane).getByText(laneIndex === 0 ? rootTitle : lastSegment)).toBeVisible() // Lane title - - itemsInTreePath(browserTree, lanePath).forEach(item => { - expect(within(lane).getByText(item)).toBeVisible() - }) -} - -const browserTree = { - '': {cb: checkTestLane}, - 'dir1': {cb: checkTestLane}, - 'dir1/success': {cb: checkTestLane}, - 'dir1/fail': {cb: checkTestLane} -} - -export class TestAdaptor extends Adaptor { - constructor(path, title) { - super() - this.path = path - this.title = title - this.parsedObjUrl = {entryId: 'entryID1'} - } - - itemAdaptor(key) { - return new TestAdaptor(join(this.path, key)) - } - - render() { - return <TestContent path={this.path} title={this.title} /> - } -} - -function TestContent({path, title}) { - if (path.endsWith('/fail')) { - throw new Error('mocked render error') - } - return <Content key={path}> - <Title title={title || basename(path)} label="test" /> - <Compartment> - { - itemsInTreePath(browserTree, path).map(itemKey => ( - <Item itemKey={itemKey} key={join(path, itemKey)}> - {itemKey} - </Item> - )) - } - </Compartment> - </Content> -} -TestContent.propTypes = { - path: PropTypes.string.isRequired, - title: PropTypes.string -} +import { checkLanes, navigateTo, selectItemAndWaitForRender, getLane, TestAdaptor, browserTree } from './conftest.spec' +import Browser, { laneErrorBoundryMessage } from './Browser' test('Test browser lane error boundry', async () => { blockConsoleOutput() diff --git a/gui/src/components/archive/QuantityItemPreview.spec.js b/gui/src/components/archive/QuantityItemPreview.spec.js index e23099e11fbe6eaf4ace43d85a3591f78bc81985..cb2aa4c66166e63617d99880ceed1fdbf47575d6 100644 --- a/gui/src/components/archive/QuantityItemPreview.spec.js +++ b/gui/src/components/archive/QuantityItemPreview.spec.js @@ -20,45 +20,31 @@ import React from 'react' import {render} from "../conftest.spec" import {QuantityItemPreview} from "./ArchiveBrowser" -describe('Test QuantityItemPreview', () => { - it('without default display unit', async () => { - render( - <QuantityItemPreview - def={{ - unit: 'meter', - type: {type_kind: 'python', type_data: 'float'}, - shape: [], - m_annotations: {} - }} - value={3.5} - /> - ) - // should be rendered in default unit system - const span = document.querySelector('span') - expect(span.textContent).toContain('3.5') - expect(span.textContent).toContain('·10') - const sup = document.querySelector('sup') - expect(sup.textContent).toContain('+10') - }) - - it('with default display unit', async () => { - render( - <QuantityItemPreview - def={{ - unit: 'meter', - type: {type_kind: 'python', type_data: 'float'}, - shape: [], - m_annotations: { - display: [{ - unit: 'mm' - }] - } - }} - value={3.5} - /> - ) - // should be rendered in default unit provided by schema - const span = document.querySelector('span') - expect(span.textContent).toContain('3500 mm') - }) +test.each([ + [ + 'without unit', + 3.5, + {}, + '3.50000'], + [ + 'without display unit', + 3.5, + {unit: 'meter'}, + '3.5·10+10 Å' + ], + [ + 'with default display unit', + 3.5, + {unit: 'meter', m_annotations: {display: [{unit: 'mm'}]}}, + '3500 mm' + ] +])('Test QuantityItemPreview %s', async (name, value, def, expected) => { + render( + <QuantityItemPreview + def={{name: 'value1', shape: [], type: {type_kind: 'python', type_data: 'float'}, ...def}} + value={value} + /> + ) + const span = document.querySelector('span') + expect(span.textContent).toContain(expected) }) diff --git a/gui/src/components/archive/Section.spec.js b/gui/src/components/archive/Section.spec.js index 1994faf6c2747c68c561e2e88e023437ed8365d2..c6933438cc9de476ac7f8f458a80c29667ff050b 100644 --- a/gui/src/components/archive/Section.spec.js +++ b/gui/src/components/archive/Section.spec.js @@ -24,7 +24,7 @@ import {Section} from "./ArchiveBrowser" import {Metainfo} from "./metainfo" import {systemMetainfoUrl} from "../../utils" import {laneContext} from './Browser' -import {TestAdaptor} from "./Browser.spec" +import {TestAdaptor} from "./conftest.spec" async function createMetainfo(data, parent, url = systemMetainfoUrl) { data._url = url @@ -36,11 +36,6 @@ const mockPackage = ({ packages: [ { name: 'testPackage', - m_annotations: { - display: [{ - unit_system: 'AU' - }] - }, section_definitions: [ { name: 'TestSection', @@ -53,42 +48,7 @@ const mockPackage = ({ }, { name: 'value2', - m_annotations: { - eln: [ - { - component: "NumberEditQuantity" - } - ] - }, - type: { type_kind: 'python', type_data: 'float' }, - unit: 'meter', - m_parent_sub_section: 'quantities' - } - ] - }, - { - name: 'TestSection', - m_annotations: { - display: [{ - unit_system: 'SI' - }] - }, - quantities: [ - { - name: 'value3', - type: { type_kind: 'python', type_data: 'float' }, - unit: 'meter', - m_parent_sub_section: 'quantities' - }, - { - name: 'value4', - m_annotations: { - eln: [ - { - component: "NumberEditQuantity" - } - ] - }, + m_annotations: {eln: [{component: "NumberEditQuantity"}]}, type: { type_kind: 'python', type_data: 'float' }, unit: 'meter', m_parent_sub_section: 'quantities' @@ -100,95 +60,32 @@ const mockPackage = ({ ] }) -describe('Test interaction between unit menu and quantities', () => { - it('Package with display unit_system', async () => { - const metainfo = await createMetainfo(mockPackage) - const defsByName = await metainfo.getDefsByName() - const def = defsByName.TestSection[0] - const adaptor = new TestAdaptor('', 'Data') - - render( - <laneContext.Provider value={{next: {}, adaptor: adaptor}}> - <Section - section={{value1: 7.5}} - def={def} - sectionIsInEln={false} - sectionIsEditable={false} - /> - </laneContext.Provider> - ) - // should be rendered in package default unit system - const numberWithUnit = document.querySelector('[data-testid="scientific-number-with-unit"]') - const span = numberWithUnit.querySelector('span') - expect(span.textContent).toContain('1.41729459') - expect(span.textContent).toContain('·10') - const sup = document.querySelector('sup') - expect(sup.textContent).toContain('+11') - }) - - it('Editable package with display unit_system', async () => { - const metainfo = await createMetainfo(mockPackage) - const defsByName = await metainfo.getDefsByName() - const def = defsByName.TestSection[0] - const adaptor = new TestAdaptor('', 'Data') +test.each([ + ['non-editable, no display unit', {value1: 7.5}, false, '7.5·10+10'], + ['editable, no display unit', {value2: 7.5}, true, '75000000000'] +])('Test editable/uneditable sections: %s', async (name, section, editable, expected) => { + const metainfo = await createMetainfo(mockPackage) + const defsByName = await metainfo.getDefsByName() + const def = defsByName.TestSection[0] + const adaptor = new TestAdaptor('', 'Data') - render( - <laneContext.Provider value={{next: {}, adaptor: adaptor}}> - <Section - section={{value2: 8.5}} - def={def} - sectionIsInEln={true} - sectionIsEditable={true} - /> - </laneContext.Provider> - ) - // should be rendered in package default unit system + render( + <laneContext.Provider value={{next: {}, adaptor: adaptor}}> + <Section + section={section} + def={def} + sectionIsInEln={editable} + sectionIsEditable={editable} + /> + </laneContext.Provider> + ) + if (editable) { const numberFieldValue = screen.getByTestId('number-edit-quantity-value') const numberFieldValueInput = within(numberFieldValue).getByRole('textbox') - // should be rendered in default unit system - await waitFor(() => expect(numberFieldValueInput.value).toEqual('160626720592.894')) - }) - - it('Section with display unit_system', async () => { - const metainfo = await createMetainfo(mockPackage) - const defsByName = await metainfo.getDefsByName() - const def = defsByName.TestSection[1] - const adaptor = new TestAdaptor('', 'Data') - - render( - <laneContext.Provider value={{next: {}, adaptor: adaptor}}> - <Section - section={{value3: 7.5}} - def={def} - sectionIsInEln={false} - sectionIsEditable={false} - /> - </laneContext.Provider> - ) - // Should be rendered in section default unit system, The determined package default unit system should be overridden. + await waitFor(() => expect(numberFieldValueInput.value).toEqual(expected)) + } else { const numberWithUnit = document.querySelector('[data-testid="scientific-number-with-unit"]') - expect(numberWithUnit.textContent).toContain('7.50000') - }) - - it('Editable Section with display unit_system', async () => { - const metainfo = await createMetainfo(mockPackage) - const defsByName = await metainfo.getDefsByName() - const def = defsByName.TestSection[1] - const adaptor = new TestAdaptor('', 'Data') - - render( - <laneContext.Provider value={{next: {}, adaptor: adaptor}}> - <Section - section={{value4: 8.5}} - def={def} - sectionIsInEln={true} - sectionIsEditable={true} - /> - </laneContext.Provider> - ) - // Should be rendered in section default unit system, The determined package default unit system should be overridden. - const numberFieldValue = screen.getByTestId('number-edit-quantity-value') - const numberFieldValueInput = within(numberFieldValue).getByRole('textbox') - await waitFor(() => expect(numberFieldValueInput.value).toEqual('8.5')) - }) + const span = numberWithUnit.querySelector('span') + expect(span.textContent).toContain(expected) + } }) diff --git a/gui/src/components/archive/conftest.spec.js b/gui/src/components/archive/conftest.spec.js index 46a0ac05ca31ad4c33e5aa9e3c5e3400135fa1f4..f032be159da885336e068ba090f8bde9aaed2b8c 100644 --- a/gui/src/components/archive/conftest.spec.js +++ b/gui/src/components/archive/conftest.spec.js @@ -19,8 +19,11 @@ import { join, basename } from 'path' import { waitFor } from '@testing-library/dom' import { screen, within, expectNoConsoleOutput } from '../conftest.spec' import userEvent from '@testing-library/user-event' -import { laneErrorBoundryMessage } from './Browser' +import { Item, Content, Compartment, Title, laneErrorBoundryMessage, Adaptor } from './Browser' import { isWaitingForUpdateTestId } from '../../utils' +import React from 'react' +import PropTypes from 'prop-types' + const crypto = require('crypto') /***************************************************************************************** @@ -326,3 +329,57 @@ export function pseudoRandomNumberGenerator(seed = 7) { return ((t ^ t >>> 14) >>> 0) / 4294967296 } } + +function checkTestLane({lane, laneIndex, lanePath, lastSegment, browserTree, rootTitle}) { + expect(within(lane).getByText(laneIndex === 0 ? rootTitle : lastSegment)).toBeVisible() // Lane title + + itemsInTreePath(browserTree, lanePath).forEach(item => { + expect(within(lane).getByText(item)).toBeVisible() + }) +} + +export const browserTree = { + '': {cb: checkTestLane}, + 'dir1': {cb: checkTestLane}, + 'dir1/success': {cb: checkTestLane}, + 'dir1/fail': {cb: checkTestLane} +} + +export class TestAdaptor extends Adaptor { + constructor(path, title) { + super() + this.path = path + this.title = title + this.parsedObjUrl = {entryId: 'entryID1'} + } + + itemAdaptor(key) { + return new TestAdaptor(join(this.path, key)) + } + + render() { + return <TestContent path={this.path} title={this.title} /> + } +} + +export function TestContent({path, title}) { + if (path.endsWith('/fail')) { + throw new Error('mocked render error') + } + return <Content key={path}> + <Title title={title || basename(path)} label="test" /> + <Compartment> + { + itemsInTreePath(browserTree, path).map(itemKey => ( + <Item itemKey={itemKey} key={join(path, itemKey)}> + {itemKey} + </Item> + )) + } + </Compartment> + </Content> +} +TestContent.propTypes = { + path: PropTypes.string.isRequired, + title: PropTypes.string +} diff --git a/gui/src/components/editQuantity/NumberEditQuantity.spec.js b/gui/src/components/editQuantity/NumberEditQuantity.spec.js index 879ac150d6635b993cf1f1bf142472ac47c73da8..6479defbef3b6847ecc290c3a6e811b6f665b427 100644 --- a/gui/src/components/editQuantity/NumberEditQuantity.spec.js +++ b/gui/src/components/editQuantity/NumberEditQuantity.spec.js @@ -53,25 +53,18 @@ describe('Test numberEditQuantity', () => { }) test.each([ - ['no default unit or unit system, defaults to global scope units', 'm', undefined, undefined, undefined, '100000000000'], - ['with display unit', 'm', 'mm', undefined, undefined, '10000'], - ['with display unit system', 'm', undefined, 'AU', undefined, '188972612462.228'], - ['with display unit and unit system', 'm', 'mm', 'AU', undefined, '10000'], - ['complex unit with no display unit', 'm**2 / second**2', undefined, undefined, undefined, '1e-9'], - ['complex unit with display unit', 'm**2 / second**2', 'Å**2 / fs**2', undefined, undefined, '1e-9'], - ['deprecated display unit in eln annotation', 'm', undefined, undefined, 'mm', '10000'] - ])('%s', async (name, unit, displayUnit, displayUnitSystem, elnUnit, expected) => { + ['no default unit or unit system, defaults to global scope units', 'm', undefined, undefined, '100000000000'], + ['with display unit', 'm', 'mm', undefined, '10000'], + ['complex unit with no display unit', 'm**2 / second**2', undefined, undefined, '1e-9'], + ['complex unit with display unit', 'm**2 / second**2', 'Å**2 / fs**2', undefined, '1e-9'], + ['deprecated display unit in eln annotation', 'm', undefined, 'mm', '10000'] + ])('%s', async (name, unit, displayUnit, elnUnit, expected) => { render( <NumberEditQuantity quantityDef={{ name: 'name', m_def: 'nomad.metainfo.metainfo.Quantity', unit: unit, - _parent: displayUnitSystem && { - m_annotations: { - display: [{unit_system: displayUnitSystem}] - } - }, m_annotations: { display: displayUnit && [{ unit: displayUnit diff --git a/gui/src/components/entry/OverviewView.js b/gui/src/components/entry/OverviewView.js index 060e677ceec1fbb17a921bf4f114d5701f87af20..2d80f11d71a72f4ffb902d712870d64c52928119 100644 --- a/gui/src/components/entry/OverviewView.js +++ b/gui/src/components/entry/OverviewView.js @@ -52,7 +52,6 @@ import ReferenceUsingCard from "./properties/ReferenceCard" import SampleHistoryUsingCard from "./properties/SampleHistoryCard" import { useEntryStore, useEntryContext, useIndex } from './EntryContext' import DeleteEntriesButton from '../uploads/DeleteEntriesButton' -import {useUnitContext} from "../units/UnitContext" function MetadataSection({title, children}) { return <Box marginTop={2} marginBottom={2}> @@ -145,7 +144,6 @@ const OverviewView = React.memo(() => { const { data: index, response: indexApiData } = useIndex() const { url, exists, editable, archive: archiveTmp, archiveApiData } = useEntryStore(required) const [sections, setSections] = useState([]) - useUnitContext(sections?.[0]?.sectionDef?._package?.name, sections?.[0]?.sectionDef?._package?.m_annotations?.display?.[0]?.unit_system) // The archive is accepted only once it is synced with the index. Notice that // we need to get the entry_id from data.entry_id, as some older entries will diff --git a/gui/src/components/units/useDisplayUnit.js b/gui/src/components/units/useDisplayUnit.js index f9dbc89e6ddbff1c3a59c02bd2b2a9d6830de41b..8036688340a99776072b817e7fa198ce3600327b 100644 --- a/gui/src/components/units/useDisplayUnit.js +++ b/gui/src/components/units/useDisplayUnit.js @@ -4,24 +4,8 @@ import {Unit} from "./Unit" import {useUnitContext} from "./UnitContext" import {getFieldProps} from "../editQuantity/StringEditQuantity" -function getUnitSystem(def) { - let unit_system - if (def?.m_def === "nomad.metainfo.metainfo.Quantity") { - unit_system = def?._parent?.m_annotations?.display?.[0]?.unit_system - if (!unit_system && def?._section?._parentSections?.[0]) { - unit_system = getUnitSystem(def._section._parentSections[0]) - } - } else if (def?.m_def === "nomad.metainfo.metainfo.Section") { - unit_system = def?.m_annotations?.display?.[0]?.unit_system - if (!unit_system && def?._parentSections?.[0]) { - unit_system = getUnitSystem(def._parentSections[0]) - } - } - return unit_system -} - export function useDisplayUnit(quantityDef) { - const {units, unitSystems} = useUnitContext() + const {units} = useUnitContext() const {raiseError} = useErrors() const defaultUnit = useMemo(() => quantityDef.unit && new Unit(quantityDef.unit), [quantityDef]) const dimension = defaultUnit && defaultUnit.dimension(false) @@ -31,7 +15,6 @@ export function useDisplayUnit(quantityDef) { const displayUnitObj = useMemo(() => { if (!dimension) return let defaultDisplayUnitObj - const section_default_unit_system = getUnitSystem(quantityDef) // TODO: If we enable the new 'Schema' scope in the unit context, we should // prioritize those values there. But for now we just read unit info from @@ -47,16 +30,13 @@ export function useDisplayUnit(quantityDef) { if (defaultDisplayUnitObj.dimension(true) !== defaultUnit.dimension(true)) { raiseError(`The provided defaultDisplayUnit for ${quantityDef.name} has incorrect dimensionality for this field.`) } - // If a unit system has been defined, use it - } else if (section_default_unit_system && unitSystems[section_default_unit_system]) { - defaultDisplayUnitObj = new Unit(unitSystems[section_default_unit_system].units[dimension].definition) - // Fallback option is the unit system in the global unit scope + // Use the global unit system defined in the schema } else { defaultDisplayUnitObj = new Unit(defaultUnit).toSystem(units) } return defaultDisplayUnitObj - }, [defaultDisplayUnit, defaultUnit, dimension, quantityDef, raiseError, unitSystems, units]) + }, [defaultDisplayUnit, defaultUnit, dimension, quantityDef, raiseError, units]) return displayUnitObj } diff --git a/nomad/datamodel/metainfo/annotations.py b/nomad/datamodel/metainfo/annotations.py index f0c3b7953ab9d5268cefa1a56ea3f109459e6619..afce100b5655f156651fde0494519beaca9f7003 100644 --- a/nomad/datamodel/metainfo/annotations.py +++ b/nomad/datamodel/metainfo/annotations.py @@ -126,7 +126,27 @@ class DisplayAnnotation(BaseModel): class QuantityDisplayAnnotation(DisplayAnnotation): - """The display settings for quantities.""" + """ + This annotations control how quantities are displayed in the GUI. Use the + key `display` to add this annotation. For example in Python: + + ```python + class Example(EntryData): + sample_id = Quantity(type=str, a_display={'visible': False}) + ``` + + or in YAML: + ```yaml + definitions: + Example: + quantities: + sample_id: + type: str + m_annotations: + display: + visible: false + ``` + """ display_unit: Optional[str] = Field( None, @@ -139,16 +159,28 @@ class QuantityDisplayAnnotation(DisplayAnnotation): class SectionDisplayAnnotation(DisplayAnnotation): - """The display settings for sections and packages.""" + """ + This annotations control how sections are displayed in the GUI. Use the + key `display` to add this annotation. For example in Python: + + ```python + class Example(MSection): + m_def = Section(a_display={ + 'visible': False + }) + ``` + + or in YAML: + ```yaml + definitions: + sections: + Example: + m_annotations: + display: + visible: false + ``` + """ - display_unit_system: Optional[str] = Field( - None, - description=strip( - """ - To determine the default display unit system for section. - """ - ), - ) order: Optional[List[str]] = Field( None, description=strip( @@ -265,11 +297,13 @@ class ELNAnnotation(AnnotationModel): defaultDisplayUnit: str = Field( None, description=""" - Allows to define a default unit to initialize a `NumberEditQuantity` with. The - unit has to be compatible with the unit of the annotation quantity and the annotated - quantity must have a unit. Only applies to quantities and with - `component=NumberEditQuantity`. + This attribute is deprecated, use the `unit` attribute of `display` + annotation instead. Allows to define a default unit to initialize a + `NumberEditQuantity` with. The unit has to be compatible with the unit + of the annotation quantity and the annotated quantity must have a unit. + Only applies to quantities and with `component=NumberEditQuantity`. """, + deprecated=True, ) minValue: Union[int, float] = Field( @@ -301,7 +335,7 @@ class ELNAnnotation(AnnotationModel): hide: List[str] = Field( None, description=""" - The annotation "hide" is deprecated. Use "visible" key of "properties" annotation instead. + This attribute is deprecated. Use `visible` attribute of `display` annotation instead. Allows you to hide certain quantities from a section editor. Give a list of quantity names. Quantities must exist in the section that this annotation is added to. Can only be used in section annotations.