From c597ffe21b496dbcc49836cc9fd7ed1c899dd15e Mon Sep 17 00:00:00 2001 From: Markus Scheidgen <markus.scheidgen@gmail.com> Date: Wed, 14 Aug 2019 10:40:29 +0200 Subject: [PATCH] Filtered code in statistics based on info code names. --- examples/statistics.py | 2 +- gui/src/components/About.js | 17 +++----------- gui/src/components/api.js | 6 +++++ .../components/dft/DFTSearchAggregations.js | 23 ++++++++++++++++--- gui/src/components/domains.js | 18 ++++----------- gui/src/components/entry/ArchiveEntryView.js | 13 ++++------- .../metaInfoBrowser/MetaInfoBrowser.js | 22 ++++++++---------- nomad/api/info.py | 9 +++++++- nomad/parsing/__init__.py | 2 +- tests/test_api.py | 4 ++++ 10 files changed, 62 insertions(+), 54 deletions(-) diff --git a/examples/statistics.py b/examples/statistics.py index 579fbfed1f..474f6d155c 100644 --- a/examples/statistics.py +++ b/examples/statistics.py @@ -48,7 +48,7 @@ mscale.register_scale(PowerScale) nomad_url = 'http://repository.nomad-coe.eu/uploads/api' host = urlparse(nomad_url).netloc.split(':')[0] http_client = RequestsClient() -http_client.set_basic_auth(host, 'admin', 'password') +http_client.set_basic_auth(host, 'admin', 'mad17no') client = SwaggerClient.from_url('%s/swagger.json' % nomad_url, http_client=http_client) diff --git a/gui/src/components/About.js b/gui/src/components/About.js index 1791c5a91b..c184d8e22d 100644 --- a/gui/src/components/About.js +++ b/gui/src/components/About.js @@ -11,6 +11,7 @@ class About extends React.Component { static propTypes = { classes: PropTypes.object.isRequired, api: PropTypes.object.isRequired, + info: PropTypes.object, domain: PropTypes.object.isRequired, raiseError: PropTypes.func.isRequired } @@ -21,21 +22,8 @@ class About extends React.Component { } }) - state = { - info: null - } - - componentDidMount() { - this.props.api.getInfo() - .then(info => this.setState({info: info})) - .catch(error => { - this.props.raiseError(error) - }) - } - render() { - const { classes, domain } = this.props - const { info } = this.state + const { classes, domain, info } = this.props return ( <div className={classes.root}> @@ -90,6 +78,7 @@ class About extends React.Component { - domain: ${info ? info.domain.name : 'loading'} - git: \`${info ? info.git.ref : 'loading'}; ${info ? info.git.version : 'loading'}\` - last commit message: *${info ? info.git.log : 'loading'}* + - codes: ${info ? info.codes.join(', ') : 'loading'} - parsers: ${info ? info.parsers.join(', ') : 'loading'} - normalizers: ${info ? info.normalizers.join(', ') : 'loading'} `}</Markdown> diff --git a/gui/src/components/api.js b/gui/src/components/api.js index de69582a0e..15388a33fa 100644 --- a/gui/src/components/api.js +++ b/gui/src/components/api.js @@ -395,12 +395,18 @@ export class ApiProviderComponent extends React.Component { const api = new Api(user) api.onStartLoading = () => this.setState({loading: this.state.loading + 1}) api.onFinishLoading = () => this.setState({loading: Math.max(0, this.state.loading - 1)}) + + api.getInfo().then(info => { + this.setState({info: info}) + }) + return api } state = { api: null, user: null, + info: null, isLoggingIn: false, loading: 0, login: (userNameToken, password, successCallback) => { diff --git a/gui/src/components/dft/DFTSearchAggregations.js b/gui/src/components/dft/DFTSearchAggregations.js index 6bf74415d2..a44ff1889f 100644 --- a/gui/src/components/dft/DFTSearchAggregations.js +++ b/gui/src/components/dft/DFTSearchAggregations.js @@ -3,6 +3,8 @@ import PropTypes from 'prop-types' import { withStyles, Grid, Card, CardContent } from '@material-ui/core' import PeriodicTable from '../search/PeriodicTable' import QuantityHistogram from '../search/QuantityHistogram' +import { compose } from 'recompose' +import { withApi } from '../api' class DFTSearchAggregations extends React.Component { static propTypes = { @@ -10,7 +12,8 @@ class DFTSearchAggregations extends React.Component { quantities: PropTypes.object.isRequired, metric: PropTypes.string.isRequired, searchValues: PropTypes.object.isRequired, - onChange: PropTypes.func.isRequired + onChange: PropTypes.func.isRequired, + info: PropTypes.object } static styles = theme => ({ @@ -70,7 +73,21 @@ class DFTSearchAggregations extends React.Component { } render() { - const { classes, quantities, metric, searchValues } = this.props + const { classes, quantities, metric, searchValues, info } = this.props + + if (quantities.code_name && info) { + // filter based on known codes, since elastic search might return 0 aggregations on + // obsolete code names + const filteredCodeNames = {} + const defaultValue = { + code_runs: 0 + } + defaultValue[metric] = 0 + info.codes.forEach(key => { + filteredCodeNames[key] = quantities.code_name[key] || defaultValue + }) + quantities.code_name = filteredCodeNames + } const quantity = (key, title, scale) => (<QuantityHistogram classes={{root: classes.quantity}} title={title || key} width={300} @@ -110,4 +127,4 @@ class DFTSearchAggregations extends React.Component { } } -export default withStyles(DFTSearchAggregations.styles)(DFTSearchAggregations) +export default compose(withApi(false), withStyles(DFTSearchAggregations.styles))(DFTSearchAggregations) diff --git a/gui/src/components/domains.js b/gui/src/components/domains.js index d4c3c28d4c..d331aa25a7 100644 --- a/gui/src/components/domains.js +++ b/gui/src/components/domains.js @@ -16,7 +16,7 @@ class DomainProviderBase extends React.Component { PropTypes.arrayOf(PropTypes.node), PropTypes.node ]).isRequired, - api: PropTypes.object.isRequired, + info: PropTypes.object, raiseError: PropTypes.func.isRequired } @@ -212,21 +212,11 @@ class DomainProviderBase extends React.Component { } } - state = { - domain: this.domains.DFT - } - - componentDidMount() { - this.props.api.getInfo().then(info => { - this.setState({domain: this.domains[info.domain.name] || this.domains.DFT}) - }).catch(error => { - this.props.raiseError(error) - }) - } - render() { + const { info } = this.props + return ( - <DomainContext.Provider value={this.state}> + <DomainContext.Provider value={{domain: info ? this.domains[info.domain.name] : this.domains.DFT}}> {this.props.children} </DomainContext.Provider> ) diff --git a/gui/src/components/entry/ArchiveEntryView.js b/gui/src/components/entry/ArchiveEntryView.js index 13d09e3906..98cbf03bf4 100644 --- a/gui/src/components/entry/ArchiveEntryView.js +++ b/gui/src/components/entry/ArchiveEntryView.js @@ -25,6 +25,7 @@ class ArchiveEntryView extends React.Component { static propTypes = { classes: PropTypes.object.isRequired, api: PropTypes.object.isRequired, + info: PropTypes.object.isRequired, raiseError: PropTypes.func.isRequired, uploadId: PropTypes.string.isRequired, calcId: PropTypes.string.isRequired @@ -94,14 +95,10 @@ class ArchiveEntryView extends React.Component { this.props.raiseError(error) }) - api.getInfo().then(info => { - this.props.api.getMetaInfo(info.domain.metainfo.all_package).then(metaInfo => { - if (!this.unmounted) { - this.setState({metaInfo: metaInfo}) - } - }) - }).catch(error => { - this.props.raiseError(error) + this.props.api.getMetaInfo(this.props.info.domain.metainfo.all_package).then(metaInfo => { + if (!this.unmounted) { + this.setState({metaInfo: metaInfo}) + } }) } diff --git a/gui/src/components/metaInfoBrowser/MetaInfoBrowser.js b/gui/src/components/metaInfoBrowser/MetaInfoBrowser.js index d1e33440c4..0e97256473 100644 --- a/gui/src/components/metaInfoBrowser/MetaInfoBrowser.js +++ b/gui/src/components/metaInfoBrowser/MetaInfoBrowser.js @@ -55,6 +55,7 @@ class MetaInfoBrowser extends Component { classes: PropTypes.object.isRequired, metainfo: PropTypes.string, api: PropTypes.object.isRequired, + info: PropTypes.object.isRequired, loading: PropTypes.number, raiseError: PropTypes.func.isRequired, history: PropTypes.object.isRequired @@ -90,18 +91,15 @@ class MetaInfoBrowser extends Component { } update(pkg) { - this.props.api.getInfo().then(info => { - this.props.api.getMetaInfo(pkg || info.domain.metainfo.all_package).then(metainfos => { - const metainfoName = this.props.metainfo || info.domain.metainfo.root_sections[0] - const definition = metainfos.get(metainfoName) - if (!definition) { - this.props.history.push(`/metainfo/${info.domain.metainfo.root_sections[0]}`) - } else { - this.setState({loadedPackage: pkg, metainfos: metainfos}) - } - }).catch(error => { - this.props.raiseError(error) - }) + const { info } = this.props.info + this.props.api.getMetaInfo(pkg || info.domain.metainfo.all_package).then(metainfos => { + const metainfoName = this.props.metainfo || info.domain.metainfo.root_sections[0] + const definition = metainfos.get(metainfoName) + if (!definition) { + this.props.history.push(`/metainfo/${info.domain.metainfo.root_sections[0]}`) + } else { + this.setState({loadedPackage: pkg, metainfos: metainfos}) + } }).catch(error => { this.props.raiseError(error) }) diff --git a/nomad/api/info.py b/nomad/api/info.py index b6652e5a2d..ee806e6ad2 100644 --- a/nomad/api/info.py +++ b/nomad/api/info.py @@ -53,6 +53,7 @@ git_info_model = api.model('GitInfo', { info_model = api.model('Info', { 'parsers': fields.List(fields.String), + 'codes': fields.List(fields.String), 'normalizers': fields.List(fields.String), 'domain': fields.Nested(model=domain_model), 'version': fields.String, @@ -68,7 +69,13 @@ class InfoResource(Resource): def get(self): """ Return information about the nomad backend and its configuration. """ return { - 'parsers': [key[8:] for key in parsing.parser_dict.keys()], + 'parsers': [ + key[key.index('/') + 1:] + for key in parsing.parser_dict.keys()], + 'codes': sorted(set([ + parser.code_name + for parser in parsing.parser_dict.values() + if isinstance(parser, parsing.MatchingParser) and parser.domain == datamodel.Domain.instance.name]), key=lambda x: x.lower()), 'normalizers': [normalizer.__name__ for normalizer in normalizing.normalizers], 'domain': { 'name': datamodel.Domain.instance.name, diff --git a/nomad/parsing/__init__.py b/nomad/parsing/__init__.py index 06396f1590..0a7274ecb8 100644 --- a/nomad/parsing/__init__.py +++ b/nomad/parsing/__init__.py @@ -67,7 +67,7 @@ import os.path from nomad import files, config from nomad.parsing.backend import AbstractParserBackend, LocalBackend, LegacyLocalBackend, JSONStreamWriter, BadContextURI, WrongContextState -from nomad.parsing.parser import Parser, LegacyParser, VaspOutcarParser, BrokenParser, MissingParser +from nomad.parsing.parser import Parser, LegacyParser, VaspOutcarParser, BrokenParser, MissingParser, MatchingParser from nomad.parsing.artificial import TemplateParser, GenerateRandomParser, ChaosParser diff --git a/tests/test_api.py b/tests/test_api.py index bc187ded0d..9823e71868 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -64,6 +64,10 @@ def get_upload_with_metadata(upload: dict) -> UploadWithMetadata: class TestInfo: def test_info(self, client): rv = client.get('/info/') + data = json.loads(rv.data) + assert 'codes' in data + assert 'parsers' in data + assert len(data['parsers']) >= len(data['codes']) assert rv.status_code == 200 -- GitLab