From e3d4c8bafc271c77f98f4e2ff3eb0907971e29cb Mon Sep 17 00:00:00 2001 From: Mohammad Nakhaee <nakhaee@physik.hu-berlin.de> Date: Thu, 22 Feb 2024 13:00:00 +0000 Subject: [PATCH] Resolve "plotly config dictionary can't be fed in from normalize function" Changelog: Fixed --- docs/reference/annotations.md | 95 +++++++++++++++++++++- gui/src/components/archive/PlotlyFigure.js | 2 +- gui/src/components/plotting/Plot.js | 3 +- gui/tests/artifacts.js | 3 + nomad/datamodel/metainfo/plot.py | 3 +- 5 files changed, 102 insertions(+), 4 deletions(-) diff --git a/docs/reference/annotations.md b/docs/reference/annotations.md index fd92de53f9..224c32ca93 100644 --- a/docs/reference/annotations.md +++ b/docs/reference/annotations.md @@ -174,7 +174,15 @@ class CustomSection(PlotSection, EntryData): heatmap = go.Heatmap(z=heatmap_data, showscale=False, connectgaps=True, zsmooth='best') figure3 = go.Figure(data=heatmap) - self.figures.append(PlotlyFigure(label='figure 3', index=0, figure=figure3.to_plotly_json())) + figure_json = figure3.to_plotly_json() + figure_json['config'] = {'staticPlot': True} + self.figures.append(PlotlyFigure(label='figure 3', index=0, figure=figure_json) +``` + +To customize the plot configuration in python one can add the config to the generated json by to_plotly_json(). + +``` +figure_json['config'] = {'staticPlot': True} ``` In YAML schemas, plots can be defined by using the PlotSection as a base class, @@ -183,4 +191,89 @@ and additionally utilizing different flavours of plot annotations. The different {{ pydantic_model('nomad.datamodel.metainfo.annotations.PlotlyGraphObjectAnnotation', heading='### PlotlyGraphObjectAnnotation') }} {{ pydantic_model('nomad.datamodel.metainfo.annotations.PlotlyExpressAnnotation', heading='### PlotlyExpressAnnotation') }} {{ pydantic_model('nomad.datamodel.metainfo.annotations.PlotlySubplotsAnnotation', heading='### PlotlySubplotsAnnotation') }} + +### plot annotations in python +For simple plots in Python schema one could use the annotations without normalizer: + +```python +from nomad.datamodel.metainfo.plot import PlotSection +from nomad.metainfo import Quantity, Section +from nomad.datamodel.data import EntryData + +class CustomSection(PlotSection, EntryData): + m_def = Section( + a_plotly_graph_object=[ + { + 'label': 'graph object 1', + 'data': {'x': '#time', 'y': '#chamber_pressure'}, + 'layout': { + 'title': { + 'text': 'Plot in section level' + }, + 'xaxis': { + 'title': { + 'text': 'x data' + } + }, + 'yaxis': { + 'title': { + 'text': 'y data' + } + } + } + }, { + 'label': 'graph object 2', + 'data': {'x': '#time', 'y': '#substrate_temperature'} + } + ], + a_plotly_express={ + 'label': 'fig 2', + 'index': 2, + 'method': 'scatter', + 'x': '#substrate_temperature', + 'y': '#chamber_pressure', + 'color': '#chamber_pressure' + }, + a_plotly_subplots={ + 'label': 'fig 1', + 'index': 1, + 'parameters': {'rows': 2, 'cols': 2}, + 'layout': { + 'title': { + 'text': 'All plots' + } + }, + 'plotly_express': [ + { + 'method': 'scatter', + 'x': '#time', + 'y': '#chamber_pressure', + 'color': '#chamber_pressure' + }, + { + 'method': 'scatter', + 'x': '#time', + 'y': '#substrate_temperature', + 'color': '#substrate_temperature' + }, + { + 'method': 'scatter', + 'x': '#substrate_temperature', + 'y': '#chamber_pressure', + 'color': '#chamber_pressure' + }, + { + 'method': 'scatter', + 'x': '#substrate_temperature', + 'y': '#chamber_pressure', + 'color': '#substrate_temperature' + } + ] + } + ) + time = Quantity(type=float, shape=['*'], unit='s', a_eln=dict(component='NumberEditQuantity')) + substrate_temperature = Quantity(type=float, shape=['*'], unit='K', a_eln=dict(component='NumberEditQuantity')) + chamber_pressure = Quantity(type=float, shape=['*'], unit='Pa', a_eln=dict(component='NumberEditQuantity')) +``` + {{ pydantic_model('nomad.datamodel.metainfo.annotations.PlotAnnotation', heading='### PlotAnnotation (Deprecated)') }} diff --git a/gui/src/components/archive/PlotlyFigure.js b/gui/src/components/archive/PlotlyFigure.js index 793d59e4cb..b0b9dc026b 100644 --- a/gui/src/components/archive/PlotlyFigure.js +++ b/gui/src/components/archive/PlotlyFigure.js @@ -232,7 +232,7 @@ const PlotlyFigure = React.memo(function PlotlyFigure({plot, section, sectionDef return plotlyGraphObj }, [plot, section, sectionDef, units]) - return <Box minWidth={500} height={500}> + return <Box minWidth={500} height={plotlyGraphObj?.layout?.height || plotlyGraphObj?.layout?.template?.layout?.height || 500}> <Plot data={plotlyGraphObj.data} layout={plotlyGraphObj.layout} diff --git a/gui/src/components/plotting/Plot.js b/gui/src/components/plotting/Plot.js index 5384eff183..0cd785215c 100644 --- a/gui/src/components/plotting/Plot.js +++ b/gui/src/components/plotting/Plot.js @@ -200,6 +200,7 @@ const Plot = React.memo(forwardRef(({ // Set the final layout. It is a combination of a default layout, the layout // set by the user and some properties of the curretly used layout. const finalLayout = useMemo(() => { + const withTitle = layout?.title?.text || layout?.template?.title?.text || layout?.annotations?.some(item => item?.text) const defaultLayout = { dragmode: 'pan', hovermode: false, @@ -210,7 +211,7 @@ const Plot = React.memo(forwardRef(({ margin: { l: theme.spacing(4), r: theme.spacing(1.5), - t: theme.spacing(layout?.title?.text ? 5 : 1), + t: theme.spacing(withTitle ? 5 : 1), b: theme.spacing(6) }, title: { diff --git a/gui/tests/artifacts.js b/gui/tests/artifacts.js index cb756dad19..fd7094cfe9 100644 --- a/gui/tests/artifacts.js +++ b/gui/tests/artifacts.js @@ -5776,6 +5776,9 @@ window.nomadArtifacts = { "m_parent_index": 2, "m_parent_sub_section": "section_definitions", "name": "PlotlyFigure", + "more": { + "label_quantity": "label" + }, "base_sections": [ "/packages/0/section_definitions/0" ], diff --git a/nomad/datamodel/metainfo/plot.py b/nomad/datamodel/metainfo/plot.py index b97ccabc09..9bd88ac583 100644 --- a/nomad/datamodel/metainfo/plot.py +++ b/nomad/datamodel/metainfo/plot.py @@ -16,7 +16,7 @@ # limitations under the License. # from nomad.datamodel.data import ArchiveSection -from nomad.metainfo import Quantity, SubSection, Package, MSection, JSON +from nomad.metainfo import Quantity, SubSection, Package, MSection, JSON, Section import plotly.express as px import plotly.graph_objs as go from plotly.subplots import make_subplots @@ -148,6 +148,7 @@ class PlotlyFigureQuantity(Quantity): class PlotlyFigure(Figure): + m_def = Section(label_quantity='label') figure = PlotlyFigureQuantity( type=JSON, description='Contains the JSON serialization for a plotly figure.' ) -- GitLab