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

Added eels parser. Improved experiment url handling.

parent dd44cc5e
Pipeline #70026 failed with stages
in 21 minutes and 18 seconds
......@@ -156,3 +156,6 @@
[submodule "dependencies/optimade-python-tools"]
path = dependencies/optimade-python-tools
url = https://github.com/markus1978/optimade-python-tools.git
[submodule "dependencies/parsers/eels"]
path = dependencies/parsers/eels
url = https://github.com/markus1978/eels.git
Subproject commit 487cceae152be217e0689d6217f420480c2a9d39
Subproject commit 43c28c292079f819f06383af123e2e933f5f55ba
Subproject commit 6bda4840730dd24f1541f596a6ee1ead70ee1ee3
Subproject commit b3159851a99a4ff6a5ee13dbe204cc0a72aff81e
Subproject commit fc60b6cfb902e1bf493a57d398e5b364f2153a9d
......@@ -26,8 +26,7 @@ class EMSEntryCards extends React.Component {
<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 [zenodo.org](https://zenodo.org).
Visit the zenodo entry to download the raw experiment data:
The data for this experiment is externally stored and managed. Download the raw experiment data:
[${data.ems.repository_url}](${data.ems.repository_url}).
The meta data describing this experiment in its original format, can be
......
......@@ -10,6 +10,19 @@ export default class EMSEntryOverview extends React.Component {
loading: PropTypes.bool
}
state = {
previewBroken: false
}
constructor(props) {
super(props)
this.handleBrokenPreview = this.handleBrokenPreview.bind(this)
}
handleBrokenPreview(event) {
this.setState({previewBroken: true})
}
render() {
const { data } = this.props
const { ems: { preview_url } } = data
......@@ -44,13 +57,19 @@ export default class EMSEntryOverview extends React.Component {
</Quantity>
<Quantity label="data" {...this.props}>
<Typography noWrap>
<a href={data.ems.repository_url}>{data.ems.repository_name}</a>
<a target="external" href={data.ems.repository_url}>{data.ems.repository_name}</a>
</Typography>
</Quantity>
</Quantity>
<Quantity label="preview" {...this.props}>
<img alt="preview" style={{maxWidth: '100%', height: 'auto'}} src={relative_preview_url}></img>
</Quantity>
{this.state.previewBroken
? data.ems.entry_repository_url && <Quantity label="preview" {...this.props}>
<Typography noWrap>
<a target="external" href={data.ems.entry_repository_url}>visit this entry on the external database</a>
</Typography>
</Quantity>
: <Quantity label="preview" {...this.props}>
<img alt="preview" style={{maxWidth: '100%', height: 'auto'}} src={relative_preview_url} onError={this.handleBrokenPreview}></img>
</Quantity>}
</Quantity>
</Quantity>
)
......
......@@ -23,6 +23,8 @@ def parse(
"""
Run the given parser on the downloaded calculation. If no parser is given,
do parser matching and use the respective parser.
Returns: A tuple with the parser instance and result backend
"""
if logger is None:
logger = utils.get_logger(__name__)
......@@ -86,12 +88,14 @@ def normalize(
return parser_backend
def normalize_all(parser_backend: LocalBackend = None, logger=None) -> LocalBackend:
def normalize_all(parser_backend: LocalBackend, logger=None) -> LocalBackend:
"""
Parse the downloaded calculation and run the whole normalizer chain.
"""
for normalizer in normalizers:
parser_backend = normalize(normalizer, parser_backend=parser_backend, logger=logger)
if normalizer.domain == parser_backend.domain:
parser_backend = normalize(
normalizer, parser_backend=parser_backend, logger=logger)
return parser_backend
......@@ -129,6 +133,6 @@ def _parse(
if show_backend:
backend.write_json(sys.stdout, pretty=True)
if show_metadata:
metadata = CalcWithMetadata(domain='dft') # TODO take domain from matched parser
metadata = CalcWithMetadata(domain=backend.domain)
metadata.apply_domain_metadata(backend)
json.dump(metadata.to_dict(), sys.stdout, indent=4)
......@@ -41,6 +41,7 @@ class EMSEntryWithMetadata(CalcWithMetadata):
# data metadata
self.repository_name: str = None
self.repository_url: str = None
self.entry_repository_url: str = None
self.preview_url: str = None
self.quantities = []
......@@ -86,6 +87,8 @@ class EMSEntryWithMetadata(CalcWithMetadata):
backend, 'data_repository_url', 'section_data', logger=logger)
self.preview_url = get_optional_backend_value(
backend, 'data_preview_url', 'section_data', logger=logger)
self.entry_repository_url = get_optional_backend_value(
backend, 'entry_repository_url', 'section_data', logger=logger)
self.group_hash = utils.hash(
self.formula,
......
......@@ -430,6 +430,13 @@ parsers = [
mainfile_mime_re=r'(application/json)|(text/.*)',
mainfile_name_re=(r'.*.aptfim')
),
LegacyParser(
name='parsers/eels', code_name='eels', domain='ems',
parser_class_name='eelsparser.EelsParserInterface',
mainfile_mime_re=r'(application/json)|(text/.*)',
mainfile_name_re=(r'.*.json'),
mainfile_contents_re=(r'"api_permalink": "https://api\.eelsdb\.eu')
),
LegacyParser(
name='parsers/qbox', code_name='qbox', domain='dft',
parser_class_name='qboxparser.QboxParser',
......
......@@ -408,6 +408,7 @@ class LocalBackend(LegacyParserBackend, metaclass=DelegatingMeta):
logger = kwargs.pop('logger', None)
super().__init__(logger=logger)
self.domain = kwargs.pop('domain', None)
self._delegate = LegacyLocalBackend(*args, **kwargs)
self.mi2_data: Dict[str, MSection] = {}
self._open_context: Tuple[str, int] = None
......
......@@ -187,7 +187,7 @@ class LegacyParser(MatchingParser):
if self.backend_factory is not None:
return self.backend_factory(meta_info, logger=logger)
return LocalBackend(meta_info, debug=False, logger=logger)
return LocalBackend(meta_info, debug=False, logger=logger, domain=self.domain)
module_name = self.parser_class_name.split('.')[:-1]
parser_class = self.parser_class_name.split('.')[-1]
......
{
"data_repository_name": "zenodo.org",
"data_repository_url": "http://zenodo.org/record/1249280",
"data_preview_url": "http://zenodo.org/record/1249280/preview.png",
"experiment_method": "atom probe tomography or field ion microscopy",
"experiment_location": "Düsseldorf, Germany",
"experiment_facility_institution": "Max-Planck-Institut für Eisenforschung GmbH",
"instrument_info": "LEAP5000",
"experiment_date_global_start": "01.01.2000 11:11:11",
"experiment_date_global_end": "01.01.2000 22:22:22",
"experiment_data_local_start": "01.01.2000 11:11:11",
"experiment_operation_method": "apt",
"experiment_imaging_method": "laser",
"specimen_description": "Pure W wire samples bulk polycrystal",
"specimen_chemistry": ["Fe", "Mn"],
"specimen_microstructure": "single crystal",
"specimen_constitution": "single phase",
"measured_nions_evaporated": 129000,
"measured_detector_hit_pos": "yes",
"measured_detector_hit_mult": "no",
"measured_detector_dead_pulses": "no",
"measured_time_of_flight": "yes",
"measured_standing_voltage": "yes",
"measured_pulse_voltage": "no"
}
{
"acquisition_mode": "STEM",
"api_permalink": "https://api.eelsdb.eu/spectra/lsmo-perovskite/",
"author": {
"name": "Dominique Imhoff",
"profile_api_url": "https://api.eelsdb.eu/author/imhoff/",
"profile_url": "https://eelsdb.eu/author/imhoff/"
},
"beamenergy": "100 kV",
"collection": "22 mrad",
"comment_count": "0",
"convergence": "7 mrad",
"darkcurrent": "Yes",
"description": "background removed",
"additionalInformation1": "calibration : 1- XAS energy reference from standard similar LSMO (maximum of MnL3 peak)",
"additionalInformation2": " 2- energy dispersion calibration of the detector from two peaks reference in low and core loss areas (STO substrate area in the multimayer system).",
"additionalInformation3": "see also LaM,OK Analyst: imhoff. Temperature: Room.",
"detector": "Parallel: 666 + CCD modified Orsay",
"download_link": "https://eelsdb.eu/wp-content/uploads/2015/09/DspecrAr6wi.msa",
"edges": "['Mn_L2,3']",
"elements": "['La', 'Sr', 'Mn', 'O']",
"formula": "(La0.7,Sr0.3)MnO3",
"gainvariation": "No",
"guntype": "Cold FEG",
"id": "21737",
"integratetime": "0.2 secs",
"keywords": "['imported from old site']",
"max_energy": "662.4 eV",
"microscope": "STEM-VG",
"min_energy": "633.29 eV",
"other_links": "[{'url': 'http://pc-web.cemes.fr/eelsdb/index.php?page=displayspec.php&id=228', 'title': 'Old EELS DB'}]",
"permalink": "https://eelsdb.eu/spectra/lsmo-perovskite/",
"probesize": "0.7 nm^2",
"published": "2008-03-04 00:00:00",
"readouts": "10",
"reference": {
"freetext": "EELS study of interfaces in magnetoresistive LSMO/STO/LSMO tunnel junctions",
"additionalInformation4": "S ... bi T., Fert A., Colliex C.,",
"additionalInformation5": "European-Physical-Journal-B., 34(2), 179-92, 2003"
},
"source_purity": "perovskite multilayers UMP CNRS-Thales Palaiseau France (laser ablation)",
"stepSize": "0.229 eV/pixel",
"title": "LSMO perovskite",
"type": "Core Loss"
}
{
"data_repository_name": "zenodo.org",
"data_repository_url": "https://zenodo.org/deposit/2704788",
"experiment_method": "multidimensional photoemission spectroscopy",
"experiment_method_abbrv": "MPES",
"experiment_location": "Hamburg, Germany",
"experiment_date": "04.2018 05.2018",
"experiment_summary": "Characterization of excited-state circular dichroism of WSe2",
"facility_institution": "DESY",
"facility_name": "FLASH",
"beamline": "PG-2",
"source_pump": "Free electron laser",
"source_probe": "Femtosecond laser",
"equipment_description": "HEXTOF detector",
"sample_description": "Bulk tungsten diselenide",
"measurement_axis": "X, Y, TOF, ADC",
"physical_axis": "kx, ky, E, tpp",
"pump_rep_rate": 1000,
"pump_pulse_duration": 100,
"pump_wavelength": 800,
"pump_spectrum": [],
"pump_photon_energy": 1.55,
"pump_size": [],
"pump_fluence": [],
"pump_polarization": "linear",
"pump_bunch": 400,
"probe_rep_rate": 1000,
"probe_pulse_duration": 100,
"probe_wavelength": 800,
"probe_spectrum": [],
"probe_photon_energy": 36.4970,
"probe_size": [],
"probe_fluence": [],
"probe_polarization": "circular",
"probe_bunch": 400,
"temporal_resolution": 100,
"extractor_voltage": 6030,
"work_distance": 4,
"lens_names": "A, B, C, D, E, F, G, H, I",
"lens_voltages": [],
"tof_distance": 0.9,
"tof_voltages": [20],
"sample_bias": 29,
"magnification": -1.5,
"detector_voltages": [],
"detector_type": "MCP",
"sensor_size": [],
"sensor_count": 4,
"sensor_pixel_size": [],
"calibration_x_to_momentum": [],
"calibration_y_to_momentum": [],
"calibration_tof_to_energy": [],
"calibration_stage_to_delay": [],
"calibration_other_converts": [],
"momentum_resolution": [0.01],
"spatial_resolution": [],
"energy_resolution": [],
"sample_id": "000",
"sample_state": "solid",
"sample_purity": 0.99,
"sample_surface_termination": "0001",
"sample_layers": "bulk",
"sample_stacking_order": "2H",
"sample_space_group": 194,
"chemical_name": "tungsten diselenide",
"chemical_formula": "WSe2",
"chemical_id_cas": "12067-46-8",
"sample_temperature": 300,
"sample_pressure": 3.85e-10,
"growth_method": "chemical vaport transport",
"preparation_method": "in-vacuum cleaving",
"sample_vendor": "HQ Graphene",
"substrate_material": "copper",
"substrate_state": "solid",
"substrate_vendor": "custom"
}
......@@ -100,7 +100,10 @@ def normalized_vasp_example(parsed_vasp_example: LocalBackend) -> LocalBackend:
@pytest.fixture
def normalized_example(parsed_example: LocalBackend) -> LocalBackend:
return run_normalize(parsed_example)
if parsed_example.domain != 'ems':
return run_normalize(parsed_example)
return None
@pytest.fixture
......@@ -232,7 +235,8 @@ def assert_normalized(backend: LocalBackend):
def test_normalizer(normalized_example: LocalBackend):
assert_normalized(normalized_example)
if normalized_example is not None: # non dft cacls are not normalized
assert_normalized(normalized_example)
def test_normalizer_faulty_matid(caplog):
......
......@@ -26,6 +26,9 @@ from nomad.parsing import LocalBackend, BadContextURI
parser_examples = [
('parsers/random', 'test/data/parsers/random_0'),
('parsers/template', 'tests/data/parsers/template.json'),
('parsers/eels', 'tests/data/parsers/eels.json'),
('parsers/aptfim', 'tests/data/parsers/aptfim.aptfim'),
('parsers/mpes', 'tests/data/parsers/mpes.meta'),
('parsers/exciting', 'tests/data/parsers/exciting/Ag/INFO.OUT'),
('parsers/exciting', 'tests/data/parsers/exciting/GW/INFO.OUT'),
('parsers/exciting', 'tests/data/parsers/exciting/nitrogen/INFO.OUT_nitrogen'),
......@@ -75,7 +78,7 @@ for parser, mainfile in parser_examples:
parser_examples = fixed_parser_examples
correct_num_output_files = 47
correct_num_output_files = 50
class TestLocalBackend(object):
......@@ -335,6 +338,7 @@ def assert_parser_dir_unchanged(previous_wd, current_wd):
def run_parser(parser_name, mainfile):
parser = parser_dict[parser_name]
result = parser.run(mainfile, logger=utils.get_logger(__name__))
result.domain = parser.domain
return add_calculation_info(result, parser_name=parser_name)
......
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