Commit dbf9c2b6 authored by Markus Scheidgen's avatar Markus Scheidgen
Browse files

Integrated the mpes parser and adapted the GUI to latest experimental data.

parent 6fa0ece4
Subproject commit c76dab1e28847bac58b247d9995fdf40d970bf41
Subproject commit 51a05bdb71586485ba3cf5e365289ee42e2a9885
Subproject commit aa26d45aafc2e19dda14da1523913eb480092218
Subproject commit ef3fe75d150b13d35abc5d9af9555708fbf3903f
......@@ -191,7 +191,6 @@ class Api {
}))
.catch(this.handleApiError)
.then(response => {
console.log(response)
const result = response.body || response.text || response.data
if (typeof result === 'string') {
try {
......
......@@ -23,6 +23,8 @@ class DomainProviderBase extends React.Component {
domains = {
DFT: {
name: 'DFT',
entryLabel: 'calculation',
searchPlaceholder: 'enter atoms, codes, functionals, or other quantity values',
/**
* A component that is used to render the search aggregations. The components needs
* to work with props: aggregations (the aggregation data from the api),
......@@ -99,6 +101,8 @@ class DomainProviderBase extends React.Component {
},
EMS: {
name: 'EMS',
entryLabel: 'experiment',
searchPlaceholder: 'enter atoms, experimental methods, or other quantity values',
/**
* A component that is used to render the search aggregations. The components needs
* to work with props: aggregations (the aggregation data from the api),
......
......@@ -2,6 +2,7 @@ import React from 'react'
import PropTypes from 'prop-types'
import { withStyles, Card, CardHeader, CardContent } from '@material-ui/core'
import RawFiles from '../entry/RawFiles'
import Markdown from '../Markdown'
class EMSEntryCards extends React.Component {
static propTypes = {
......@@ -11,7 +12,10 @@ class EMSEntryCards extends React.Component {
}
static styles = theme => ({
root: {}
root: {},
description: {
marginBottom: theme.spacing.unit * 3
}
})
render() {
......@@ -19,8 +23,16 @@ class EMSEntryCards extends React.Component {
return (
<Card className={classes.root}>
<CardHeader title="Raw files" />
<CardHeader title="Raw Data and Meta Data Files" />
<CardContent classes={{root: classes.cardContent}}>
<Markdown classes={{root: classes.description}}>{`
The data for this experiment was uploaded to [xenodo.org](https://xenodo.org).
Visit the xenodo entry to download the raw experiment data:
[${data.repository_url}](${data.repository_url}).
The meta data describing this experiment in its original format, can be
downloaded here directly:
`}</Markdown>
<RawFiles data={data} />
</CardContent>
</Card>
......
......@@ -2,6 +2,7 @@ import React from 'react'
import PropTypes from 'prop-types'
import Quantity from '../Quantity'
import { Typography } from '@material-ui/core'
import { apiBase } from '../../config'
export default class EMSEntryOverview extends React.Component {
static propTypes = {
......@@ -11,8 +12,21 @@ export default class EMSEntryOverview extends React.Component {
render() {
const { data } = this.props
const { preview_url } = data
let relative_preview_url = null
if (!preview_url) {
relative_preview_url = 'broken'
} else if (preview_url.indexOf('http://') === 0 || preview_url.indexOf('https://') === 0) {
relative_preview_url = preview_url
} else {
const dirname = data.mainfile.substring(0, data.mainfile.lastIndexOf('/') + 1)
relative_preview_url = `${apiBase}/raw/${data.upload_id}/${dirname ? dirname + '/' : ''}${preview_url}`
}
return (
<Quantity column>
<Quantity quantity="experiment_summary" label="summary" noWrap {...this.props} />
<Quantity row>
<Quantity column>
<Quantity row>
......@@ -33,7 +47,8 @@ export default class EMSEntryOverview extends React.Component {
</Quantity>
</Quantity>
<Quantity label="preview" {...this.props}>
<img alt="preview" style={{maxWidth: '100%', height: 'auto'}} src={data.preview_url}></img>
<img alt="preview" style={{maxWidth: '100%', height: 'auto'}} src={relative_preview_url}></img>
</Quantity>
</Quantity>
</Quantity>
)
......
......@@ -66,9 +66,11 @@ class EMSSearchAggregations extends React.Component {
<Grid container spacing={24} className={classes.quantityGrid}>
<Grid item xs={6}>
{quantity('method', 'Method')}
{quantity('probing_method', 'Probing')}
</Grid>
<Grid item xs={6}>
{quantity('experiment_location', 'Location')}
{quantity('sample_microstructure', 'Sample structure')}
{quantity('sample_constituents', 'Sample constituents')}
</Grid>
</Grid>
</div>
......
......@@ -85,10 +85,12 @@ class ArchiveEntryView extends React.Component {
this.props.raiseError(error)
})
api.getMetaInfo().then(metaInfo => {
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)
})
......
......@@ -131,9 +131,9 @@ class RepoEntryView extends React.Component {
{new Date(calcData.upload_time * 1000).toLocaleString()}
</Typography>
</Quantity>
<Quantity quantity="calc_id" label='calculation id' noWrap {...quantityProps} />
<Quantity quantity="calc_id" label={`${domain.entryLabel} id`} noWrap {...quantityProps} />
<Quantity quantity='mainfile' loading={loading} noWrap {...quantityProps} />
<Quantity quantity="calc_hash" label='calculation hash' loading={loading} noWrap {...quantityProps} />
<Quantity quantity="calc_hash" label={`${domain.entryLabel} hash`} loading={loading} noWrap {...quantityProps} />
<Quantity quantity="last_processing" label='last processing' loading={loading} placeholder="not processed" noWrap {...quantityProps}>
<Typography noWrap>
{new Date(calcData.last_processing * 1000).toLocaleString()}
......
......@@ -216,7 +216,7 @@ class SearchPage extends React.Component {
<SearchBar classes={{autosuggestRoot: classes.searchBar}}
fullWidth fullWidthInput={false} helperText={helperText}
label="search"
placeholder="enter atoms, codes, functionals, or other quantity values"
placeholder={domain.searchPlaceholder}
data={data} searchValues={searchValues}
InputLabelProps={{
shrink: true
......
......@@ -22,6 +22,7 @@ import os.path
from flask import send_file
from flask_restplus import abort, Resource
import json
import importlib
import nomad_meta_info
......@@ -125,11 +126,11 @@ class MetainfoResource(Resource):
return load_metainfo(metainfo_package_name), 200
except FileNotFoundError:
parser_prefix = metainfo_package_name[:-len('.nomadmetainfo.json')]
alternative_path = os.path.join(
metainfo_main_path,
'../{0}parser/{0}.nomadmetainfo.json'.format(parser_prefix))
try:
return load_metainfo(alternative_path, is_path=True), 200
return load_metainfo(dict(
parser='%sparser' % parser_prefix,
path='%s.nomadmetainfo.json' % parser_prefix)), 200
except FileNotFoundError:
abort(404, message='The metainfo %s does not exist.' % metainfo_package_name)
......@@ -137,24 +138,53 @@ class MetainfoResource(Resource):
metainfo_main_path = os.path.dirname(os.path.abspath(nomad_meta_info.__file__))
def load_metainfo(package_name: str, is_path: bool = False, loaded_packages: Dict[str, Any] = None) -> Dict[str, Any]:
def load_metainfo(
package_name_or_dependency: str, dependency_source: str = None,
loaded_packages: Dict[str, Any] = None) -> Dict[str, Any]:
"""
Loads the given metainfo package and all its dependencies. Returns a dict with
all loaded package_names and respective packages.
Arguments:
package_name: The name of the package, or a path to .nomadmetainfo.json file.
is_path: True will interpret package_name as (relative) path.
package_name_or_dependency: The name of the package, or a nomadmetainfo dependency object.
dependency_source: The path of the metainfo that uses this function to load a relative dependency.
loaded_packages: Give a dict and the function will added freshly loaded packages
to it and return it.
"""
if loaded_packages is None:
loaded_packages = {}
if is_path:
metainfo_path = package_name
else:
if isinstance(package_name_or_dependency, str):
package_name = package_name_or_dependency
metainfo_path = os.path.join(metainfo_main_path, package_name)
else:
dependency = package_name_or_dependency
if 'relativePath' in dependency:
if dependency_source is None:
raise Exception(
'Can only load relative dependency from within another metainfo package')
metainfo_path = os.path.join(
os.path.dirname(dependency_source), dependency['relativePath'])
elif 'metainfoPath' in dependency:
metainfo_path = os.path.join(metainfo_main_path, dependency['metainfoPath'])
elif 'parser' in dependency:
parser = dependency['parser']
path = dependency['path']
try:
parser_module = importlib.import_module(parser).__file__
except Exception:
raise Exception('Parser not installed %s for metainfo path %s' % (parser, metainfo_path))
parser_directory = os.path.dirname(parser_module)
metainfo_path = os.path.join(parser_directory, path)
else:
raise Exception('Invalid dependency type in metainfo package %s' % metainfo_path)
package_name = os.path.basename(metainfo_path)
package_name = os.path.basename(package_name)
......@@ -167,15 +197,6 @@ def load_metainfo(package_name: str, is_path: bool = False, loaded_packages: Dic
loaded_packages[package_name] = metainfo_json
for dependency in metainfo_json.get('dependencies', []):
if 'relativePath' in dependency:
dependency_path = os.path.join(
os.path.dirname(metainfo_path), dependency['relativePath'])
elif 'metainfoPath' in dependency:
dependency_path = os.path.join(metainfo_main_path, dependency['metainfoPath'])
else:
raise Exception(
'Invalid dependency type in metainfo package %s' % metainfo_path)
load_metainfo(dependency_path, is_path=True, loaded_packages=loaded_packages)
load_metainfo(dependency, dependency_source=metainfo_path, loaded_packages=loaded_packages)
return loaded_packages
......@@ -65,8 +65,14 @@ class RawFileFromPathResource(Resource):
"""
upload_filepath = path
upload_files = UploadFiles.get(
upload_id, create_authorization_predicate(upload_id))
# TODO find a better way to all access to certain files
if os.path.basename(path).endswith('.png'):
def authorization_predicate(*args, **kwargs):
return True
else:
authorization_predicate = create_authorization_predicate(upload_id)
upload_files = UploadFiles.get(upload_id, authorization_predicate)
if upload_files is None:
abort(404, message='The upload with id %s does not exist.' % upload_id)
......
......@@ -32,11 +32,17 @@ class EMSEntryWithMetadata(CalcWithMetadata):
self.atoms: List[str] = []
self.n_atoms: int = 0
self.chemical: str = None
self.sample_constituents: str = None
self.sample_microstructure: str = None
# general metadata
self.experiment_summary: str = None
self.experiment_location: str = None
self.experiment_time: str = None
# method
self.method: str = None
self.probing_method: str = None
# data metadata
self.repository_name: str = None
......@@ -63,13 +69,22 @@ class EMSEntryWithMetadata(CalcWithMetadata):
self.atoms.sort()
self.chemical = get_optional_backend_value(
backend, 'sample_chemical_name', 'section_sample', logger=logger)
self.sample_microstructure = get_optional_backend_value(
backend, 'sample_microstructure', 'section_sample', logger=logger)
self.sample_constituents = get_optional_backend_value(
backend, 'sample_constituents', 'section_sample', logger=logger)
self.experiment_summary = get_optional_backend_value(
backend, 'experiment_summary', 'section_experiment', logger=logger)
self.experiment_location = get_optional_backend_value(
backend, 'experiment_location', 'section_experiment', logger=logger)
self.experiment_time = get_optional_backend_value(
backend, 'experiment_time', 'section_experiment', logger=logger)
self.method = get_optional_backend_value(
backend, 'experiment_method_name', 'section_experiment', logger=logger)
backend, 'experiment_method_name', 'section_method', logger=logger)
self.probing_method = get_optional_backend_value(
backend, 'probing_method', 'section_method', logger=logger)
self.repository_name = get_optional_backend_value(
backend, 'data_repository_name', 'section_data', logger=logger)
......@@ -109,8 +124,12 @@ Domain(
aggregations=len(ase.data.chemical_symbols)),
method=DomainQuantity(
'The experimental method used.', aggregations=20),
experiment_location=DomainQuantity(
'The used basis set functions.', aggregations=10),
probing_method=DomainQuantity(
'The used probing method.', aggregations=10),
sample_microstructure=DomainQuantity(
'The sample micro structure.', aggregations=10),
sample_constituents=DomainQuantity(
'The sample constituents.', aggregations=10),
quantities=DomainQuantity(
'All quantities that are used by this calculation',
metric=('quantities', 'value_count')
......
......@@ -370,7 +370,7 @@ parsers = [
name='parsers/mpes', code_name='mpes', domain='EMS',
parser_class_name='mpesparser.MPESParserInterface',
mainfile_mime_re=r'(application/json)|(text/.*)',
mainfile_name_re=(r'.*')
mainfile_name_re=(r'.*_data.meta')
)
]
......
......@@ -587,8 +587,13 @@ class TestArchive(UploadFilesBasedTests):
rv = client.get('/archive/%s' % 'doesnt/exist', headers=auth_headers)
assert rv.status_code == 404
def test_get_metainfo(self, client):
rv = client.get('/archive/metainfo/all.nomadmetainfo.json')
@pytest.mark.parametrize('info', [
'all.nomadmetainfo.json',
'all.experimental.nomadmetainfo.json',
'vasp.nomadmetainfo.json',
'mpes.nomadmetainfo.json'])
def test_get_metainfo(self, client, info):
rv = client.get('/archive/metainfo/%s' % info)
assert rv.status_code == 200
metainfo = json.loads((rv.data))
assert len(metainfo) > 0
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment