Commit 535d0c11 authored by Markus Scheidgen's avatar Markus Scheidgen
Browse files

Merge branch 'v1.0.5' into 'master'

Merge for release v1.0.5

See merge request !598
parents 9c0b492e 205d57de
Pipeline #126666 passed with stage
in 4 minutes and 13 seconds
......@@ -338,7 +338,7 @@ function EditMetaDataDialog({...props}) {
}, [])
const createNewDatasets = useCallback(() => {
const promises = actions.filter(action => action.create_dataset).map(action => api.post(`/datasets`, {dataset_name: action.create_dataset}))
const promises = actions.filter(action => action.create_dataset).map(action => api.post(`/datasets/`, {dataset_name: action.create_dataset}))
return Promise.all(promises)
}, [api, actions])
......
......@@ -355,6 +355,7 @@ function UploadPage() {
})
.catch((error) => {
if (error instanceof DoesNotExist && deleteClicked) {
history.push(getUrl('uploads', location))
return
}
if (!hasUpload && error.apiMessage) {
......@@ -363,17 +364,15 @@ function UploadPage() {
raiseError(error)
}
})
}, [api, hasUpload, uploadId, pagination, deleteClicked, raiseError, setData, setApiData])
}, [api, hasUpload, uploadId, pagination, deleteClicked, raiseError, setData, setApiData, location, history])
// constant fetching of upload data when necessary
useEffect(() => {
if (isProcessing) {
const interval = setInterval(fetchData(), 1000)
return () => clearInterval(interval)
} else if (deleteClicked) {
history.push(getUrl('uploads', location))
}
}, [fetchData, isProcessing, deleteClicked, history, location])
}, [fetchData, isProcessing])
// initial fetching of upload data
useEffect(fetchData(), [fetchData])
......
......@@ -11,7 +11,7 @@ global.nomadEnv = {
'appBase': 'http://nomad-lab.eu/prod/rae/beta',
'debug': false,
'version': {
'label': '1.0.4',
'label': '1.0.5',
'isBeta': false,
'isTest': true,
'usesBetaData': true,
......
......@@ -156,16 +156,14 @@ def parser_metadata():
import yaml
import os
import os.path
from glob import glob
parsers_metadata = {}
parsers_path = 'dependencies/parsers'
for parser_dir in os.listdir(parsers_path):
parser_path = os.path.join(parsers_path, parser_dir)
parser_metadata_file = os.path.join(parser_path, 'metadata.yaml')
if os.path.exists(parser_metadata_file):
with open(parser_metadata_file) as f:
parser_metadata = yaml.load(f, Loader=yaml.FullLoader)
parsers_metadata[parser_dir] = parser_metadata
parsers_path = './dependencies/parsers'
for parser_metadata_file in sorted(glob(f'{parsers_path}/**/metadata.yaml', recursive=True)):
with open(parser_metadata_file) as f:
parser_metadata = yaml.load(f, Loader=yaml.FullLoader)
parsers_metadata[os.path.basename(os.path.dirname(parser_metadata_file))] = parser_metadata
parsers_metadata = {
key: parsers_metadata[key]
......@@ -216,66 +214,89 @@ def update_parser_readmes(parser):
generic_fn = './README.parsers.md'
parser_path = './dependencies/parsers/'
for num, ddir in enumerate(sorted(glob(parser_path + '*/')), start=1):
if parser is not None and parser != ddir.split(os.sep)[-2]:
print(f'Skip {ddir}')
continue
_, parser_dirname = os.path.split(ddir)
print('{} Working on {}' .format(num, parser_dirname))
# Open general template
with open(generic_fn, 'r') as generic: # read only
generic_contents = generic.read()
# Open general template
with open(generic_fn, 'r') as generic: # read only
body = generic.read()
# Replace the comment at the top of the gereral template
generic_contents = re.sub(
rf'\*\*\*Note:\*\* This is a general README file for NOMAD parsers, '
rf'consult the README of specific parser projects for more detailed '
rf'information!\*\n\n', '', generic_contents)
# Open local YAML metadata file
local_mdata = ddir + 'metadata.yaml'
with open(local_mdata, 'r') as mdata_f:
mdata = yaml.load(mdata_f, Loader=yaml.FullLoader)
if mdata.get('codeName', '').strip() == '':
mdata['codeName'] = os.path.basename(os.path.dirname(ddir))
if 'preamble' not in mdata:
mdata['preamble'] = ''
def open_metadata(path):
# read local yaml metadata file
with open(path, 'r') as metadata_f:
try:
metadata = yaml.load(metadata_f, Loader=yaml.FullLoader)
except Exception as e:
print(f'Error reading metadata.yaml: {e}')
metadata = None
return metadata
def replace(metadata, contents, path):
# replace placelder in contents with metadata values
for key in metadata.keys():
replace = metadata.get(key)
if replace is None:
continue
print(f'\tReplacing {key} with {replace}')
contents = re.sub(rf'\${key}\$', replace, contents)
# save file
with open(path, 'w') as f:
f.write(contents.strip())
f.write('\n')
for local_readme in sorted(glob(f'{parser_path}/*/{local_fn}')):
parser_dir = os.path.dirname(local_readme)
project_name = os.path.basename(parser_dir)
print(f'Working on {parser_dir}')
contents = generic_contents
# if metadata file under the parser directory exists, it is a single parser project
single = os.path.isfile(os.path.join(parser_dir, 'metadata.yaml'))
if single:
metadata = open_metadata(os.path.join(parser_dir, 'metadata.yaml'))
# git path is given by nomad-parser-codename
metadata['gitPath'] = f'nomad-parser-{project_name}'
parser_header, parser_specs = '', ''
else:
# replace header for the single parser with that for a group of parsers
parser_header_re = r'(\nThis is a NOMAD parser[\s\S]+?Archive format\.\n)'
parser_header = re.search(parser_header_re, contents).group(1)
group_header = 'This is a collection of the NOMAD parsers for the following $codeName$ codes:\n\n$parserList$'
contents = re.sub(parser_header_re, group_header, contents)
# remove individual parser specs
parser_specs_re = r'(For \$codeLabel\$ please provide[\s\S]+?\$tableOfFiles\$)\n\n'
parser_specs = re.search(parser_specs_re, contents).group(1)
contents = re.sub(parser_specs_re, '', contents)
metadata = dict(
gitPath=f'{project_name}-parsers',
parserGitUrl=f'https://github.com/nomad-coe/{project_name}-parsers.git',
parserSpecific='')
if metadata.get('codeName', '').strip() == '':
metadata['codeName'] = project_name
if 'preamble' not in metadata:
metadata['preamble'] = ''
# if this is a group of parser, find all individdual parsers and write the
# parser specs
parser_list = ''
for index, local_metadata in enumerate(sorted(glob(f'{parser_dir}/*/*/metadata.yaml'))):
metadata_parser = open_metadata(local_metadata)
# contents is simply the parser header and specs
contents_parser = f'{parser_header}\n{parser_specs}'
replace(metadata_parser, contents_parser, os.path.join(os.path.dirname(local_metadata), local_fn))
# add the codename to the list of parsers for the group header
codelabel = metadata_parser.get('codeLabel', os.path.basename(os.path.dirname(local_metadata)))
codeurl = metadata_parser.get('codeUrl', '')
parser_list = rf'{parser_list}{index + 1}. [{codelabel}]({codeurl})\n'
metadata['parserList'] = parser_list.strip()
# Find & Replace Parser`s metadata on its README file
local_readme = ddir + local_fn
with open(local_readme, 'w') as local:
for key in mdata.keys():
ignore = ['codeLabelStyle', 'parserDirName']
if key in ignore:
continue
find = r'\$' + key + r'\$'
replace = mdata[key]
print(f'\tReplacing {key} with {replace}')
if key == 'parserSpecific':
if mdata[key] != '':
replace = r'## Parser Specific\n' + replace
body = re.sub(find, replace, body)
# Extra: to replace the codeName (there's no YAML key for this)
key = 'codeName'
print('\tReplacing', key)
find = r'\$' + key + r'\$'
replace = parser_dirname
body = re.sub(find, replace, body)
# Extra: to replace the comment at the top of the gereral template
find = (
r'\*\*\*Note:\*\* This is a general README file for NOMAD parsers, '
r'consult the README of specific parser projects for more detailed '
r'information!\*\n\n')
replace = ''
print('\tReplacing the top comment')
# print('\t', find, ' -> ', replace)
body = re.sub(find, replace, body)
# save file
local.seek(0) # go to the top
local.write(body.strip())
local.truncate()
replace(metadata, contents, local_readme)
@dev.command(help='Adds a few pieces of data to NOMAD.')
......
......@@ -311,7 +311,7 @@ datacite = NomadConfig(
)
meta = NomadConfig(
version='1.0.4',
version='1.0.5',
commit=gitinfo.commit,
deployment='devel',
label=None,
......
......@@ -226,6 +226,22 @@ class EnergyEntry(Atomic):
Value of the potential energy.
''')
kinetic = Quantity(
type=np.dtype(np.float64),
shape=[],
unit='joule',
description='''
Value of the kinetic energy.
''')
correction = Quantity(
type=np.dtype(np.float64),
shape=[],
unit='joule',
description='''
Value of the correction to the energy.
''')
class Energy(MSection):
'''
......@@ -241,6 +257,7 @@ class Energy(MSection):
Contains the value and information regarding the total energy of the system.
''')
# TODO this should be removed and replaced by correction in EnergyEntry
current = SubSection(
sub_section=EnergyEntry.m_def,
description='''
......@@ -257,7 +274,7 @@ class Energy(MSection):
Contains the value and information regarding the converged zero-point
vibrations energy calculated using the method described in zero_point_method.
''')
# this should be removed and replaced by electronic.kinetic
kinetic_electronic = SubSection(
sub_section=EnergyEntry.m_def,
description='''
......@@ -265,6 +282,13 @@ class Energy(MSection):
kinetic energy.
''')
electronic = SubSection(
sub_section=EnergyEntry.m_def,
description='''
Contains the value and information regarding the self-consistent electronic
energy.
''')
correlation = SubSection(
sub_section=EnergyEntry.m_def,
description='''
......@@ -384,7 +408,7 @@ class Energy(MSection):
''',
repeats=True)
# TODO determine if correction can be generalized in EnergyEntry
# TODO remove this should be be entropy.correction
correction_entropy = SubSection(
sub_section=EnergyEntry.m_def,
description='''
......@@ -393,6 +417,7 @@ class Energy(MSection):
in account. Defined consistently with XC_method.
''')
# TODO remove this should be in electrostatic.correction
correction_hartree = SubSection(
sub_section=EnergyEntry.m_def,
description='''
......@@ -401,6 +426,7 @@ class Energy(MSection):
density electrostatic energy. Defined consistently with XC_method.
''')
# TODO remove this should be in xc.correction
correction_xc = SubSection(
sub_section=EnergyEntry.m_def,
description='''
......@@ -677,6 +703,22 @@ class BandGap(MSection):
The lowest unoccupied energy.
""")
value_fundamental = Quantity(
type=np.dtype(np.float64),
shape=[],
unit='joule',
description='''
GW fundamental band gap
''')
value_optical = Quantity(
type=np.dtype(np.float64),
shape=[],
unit='joule',
description='''
GW optical band gap
''')
class BandEnergies(MSection):
'''
......@@ -762,6 +804,71 @@ class BandEnergies(MSection):
Values of the band energies.
''')
qp_linearization_prefactor = Quantity(
type=np.dtype(np.float64),
shape=['n_spin_channels', 'n_kpoints', 'n_bands'],
description='''
Values of the GW quasi particle linearization pre-factor.
''')
value_xc_potential = Quantity(
type=np.dtype(np.float64),
shape=['n_spin_channels', 'n_kpoints', 'n_bands'],
unit='joule',
description='''
Diagonal matrix elements of the GW exchange-correlation potential.
''')
value_correlation = Quantity(
type=np.dtype(np.float64),
shape=['n_spin_channels', 'n_kpoints', 'n_bands'],
unit='joule',
description='''
Diagonal matrix elements of the GW correlation energy.
''')
value_exchange = Quantity(
type=np.dtype(np.float64),
shape=['n_spin_channels', 'n_kpoints', 'n_bands'],
unit='joule',
description='''
Diagonal matrix elements of the GW exchange energy.
''')
value_xc = Quantity(
type=np.dtype(np.float64),
shape=['n_spin_channels', 'n_kpoints', 'n_bands'],
unit='joule',
description='''
Diagonal matrix elements of the GW exchange-correlation energy.
''')
value_qp = Quantity(
type=np.dtype(np.float64),
shape=['n_spin_channels', 'n_kpoints', 'n_bands'],
unit='joule',
description='''
Diagonal matrix elements of the GW quasi-particle energy.
''')
value_ks = Quantity(
type=np.dtype(np.float64),
shape=['n_spin_channels', 'n_kpoints', 'n_bands'],
unit='joule',
description='''
Diagonal matrix elements of the Kohn-Sham energy.
''')
value_ks_xc = Quantity(
type=np.dtype(np.float64),
shape=['n_spin_channels', 'n_kpoints', 'n_bands'],
unit='joule',
description='''
Diagonal matrix elements of the Kohn-Sham exchange-correlation energy.
''')
band_gap = SubSection(sub_section=BandGap.m_def, repeats=True)
class BandStructure(MSection):
'''
......@@ -966,6 +1073,14 @@ class MultipolesEntry(Atomic):
m_def = Section(validate=False)
origin = Quantity(
type=np.dtype(np.float64),
shape=[3],
unit='meter',
description='''
Origin in cartesian space.
''')
n_multipoles = Quantity(
type=int,
shape=[],
......@@ -1014,118 +1129,6 @@ class Multipoles(MSection):
higher_order = SubSection(sub_section=MultipolesEntry.m_def, repeats=True)
class GWBandEnergies(BandEnergies):
'''
Contains information regarding the GW eigenvalues.
'''
m_def = Section(validate=False)
n_spin_channels = Quantity(
type=int,
shape=[],
description='''
Number of spin channels.
''')
qp_linearization_prefactor = Quantity(
type=np.dtype(np.float64),
shape=['n_spin_channels', 'n_kpoints', 'n_bands'],
description='''
Values of the GW quasi particle linearization pre-factor.
''')
value_xc_potential = Quantity(
type=np.dtype(np.float64),
shape=['n_spin_channels', 'n_kpoints', 'n_bands'],
unit='joule',
description='''
Diagonal matrix elements of the GW exchange-correlation potential.
''')
value_correlation = Quantity(
type=np.dtype(np.float64),
shape=['n_spin_channels', 'n_kpoints', 'n_bands'],
unit='joule',
description='''
Diagonal matrix elements of the GW correlation energy.
''')
value_exchange = Quantity(
type=np.dtype(np.float64),
shape=['n_spin_channels', 'n_kpoints', 'n_bands'],
unit='joule',
description='''
Diagonal matrix elements of the GW exchange energy.
''')
value_xc = Quantity(
type=np.dtype(np.float64),
shape=['n_spin_channels', 'n_kpoints', 'n_bands'],
unit='joule',
description='''
Diagonal matrix elements of the GW exchange-correlation energy.
''')
value_qp = Quantity(
type=np.dtype(np.float64),
shape=['n_spin_channels', 'n_kpoints', 'n_bands'],
unit='joule',
description='''
Diagonal matrix elements of the GW quasi-particle energy.
''')
value_ks = Quantity(
type=np.dtype(np.float64),
shape=['n_spin_channels', 'n_kpoints', 'n_bands'],
unit='joule',
description='''
Diagonal matrix elements of the Kohn-Sham energy.
''')
value_ks_xc = Quantity(
type=np.dtype(np.float64),
shape=['n_spin_channels', 'n_kpoints', 'n_bands'],
unit='joule',
description='''
Diagonal matrix elements of the Kohn-Sham exchange-correlation energy.
''')
class GW(MSection):
'''
Section containing the results of a GW calculation.
'''
m_def = Section(validate=False)
fermi_energy = Quantity(
type=np.dtype(np.float64),
shape=[],
unit='joule',
description='''
GW Fermi energy
''')
fundamental_gap = Quantity(
type=np.dtype(np.float64),
shape=[],
unit='joule',
description='''
GW fundamental band gap
''')
optical_gap = Quantity(
type=np.dtype(np.float64),
shape=[],
unit='joule',
description='''
GW optical band gap
''')
eigenvalues = SubSection(sub_section=GWBandEnergies.m_def, repeats=True)
class Thermodynamics(MSection):
'''
Section containing results related to a thermodynamics calculation.
......@@ -1577,8 +1580,6 @@ class BaseCalculation(MSection):
band_structure_phonon = SubSection(sub_section=BandStructure.m_def, repeats=True)
gw = SubSection(sub_section=GW.m_def, repeats=True)
thermodynamics = SubSection(sub_section=Thermodynamics.m_def, repeats=True)
excited_states = SubSection(sub_section=ExcitedStates.m_def, repeats=True)
......
......@@ -72,5 +72,5 @@ based on nomad@fairdi's metainfo:
:members:
'''
from nomad.parsing.parser import Parser, BrokenParser, MissingParser, MatchingParser, FairdiParser
from nomad.parsing.parser import Parser, BrokenParser, MissingParser, MatchingParser, MatchingParserInterface
from nomad.parsing.artificial import TemplateParser, GenerateRandomParser, ChaosParser, EmptyParser
......@@ -13,7 +13,7 @@
# limitations under the License.
from typing import Dict, Any, List
from typing import List
import os
import logging
import numpy as np
......@@ -21,7 +21,6 @@ import re
from ase.data import chemical_symbols
from nomad.datamodel import EntryArchive
from nomad.parsing import FairdiParser
from nomad.parsing.file_parser import TextParser, Quantity
from nomad.datamodel.metainfo.simulation.run import Run, Program
from nomad.datamodel.metainfo.simulation.method import Method
......@@ -30,21 +29,20 @@ from nomad.datamodel.metainfo.simulation.calculation import (
Calculation, Energy, EnergyEntry, Forces, ForcesEntry, Thermodynamics)
class BasicParser(FairdiParser):
class BasicParser:
'''
Defines a fairdi parser that parse basic quantities for sections method, system and
single_configuration_calculation.
Arguments:
specifications: dictionary that will be passed on to FairdiParser
code_name: name of the code
units_mapping: dictionary of nomad units for basic quantities such as length
auxiliary_files: re pattern to match auxilliary files from mainfile. If no files
are found will match files in working directory.
kwargs: metainfo_key: re pattern pairs used to parse quantity
'''
def __init__(self, specifications: Dict[str, Any], **kwargs):
super().__init__(**specifications)
self.specifications = specifications
def __init__(self, code_name: str, **kwargs):
self.code_name = code_name
self.units_mapping = kwargs.get('units_mapping', {})
self.auxilliary_files = kwargs.get('auxilliary_files', '')
self.mainfile_parser = TextParser()
......@@ -129,7 +127,7 @@ class BasicParser(FairdiParser):
sections[n].m_parent.m_remove_sub_section(definition, n)
sec_run = self.archive.m_create(Run)
sec_run.program = Program(name=self.specifications.get('code_name', ''))
sec_run.program = Program(name=self.code_name)
energy_unit = self.units_mapping.get('energy', 1.0)
length_unit = self.units_mapping.get('length', 1.0)
......