Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
nomad-lab
nomad-FAIR
Commits
9301b014
Commit
9301b014
authored
Oct 10, 2019
by
Alvin Noe Ladines
Browse files
test optimade
parent
f206487f
Changes
6
Hide whitespace changes
Inline
Side-by-side
nomad/app/optimade/endpoints.py
View file @
9301b014
...
...
@@ -29,7 +29,7 @@ def base_request_args():
if
request
.
args
.
get
(
'response_format'
,
'json'
)
!=
'json'
:
abort
(
400
,
'Response format is not supported.'
)
properties_str
=
request
.
args
.
get
(
're
sponse
_fields'
,
None
)
properties_str
=
request
.
args
.
get
(
're
quest
_fields'
,
None
)
if
properties_str
is
not
None
:
return
properties_str
.
split
(
','
)
return
None
...
...
@@ -67,6 +67,9 @@ class CalculationList(Resource):
# order_by='optimade.%s' % sort) # TODO map the Optimade property
available
=
result
[
'pagination'
][
'total'
]
print
(
result
[
'results'
][
0
][
'optimade'
].
keys
())
raise
return
dict
(
meta
=
Meta
(
...
...
@@ -104,6 +107,8 @@ class Calculation(Resource):
if
available
==
0
:
abort
(
404
,
'The calculation with id %s does not exist'
%
id
)
print
(
'================'
,
result
[
'results'
][
0
])
raise
return
dict
(
meta
=
Meta
(
query
=
request
.
url
,
returned
=
1
),
data
=
CalculationDataObject
(
result
[
'results'
][
0
],
request_fields
=
request_fields
)
...
...
nomad/app/optimade/filterparser.py
View file @
9301b014
...
...
@@ -32,12 +32,17 @@ quantities: Dict[str, Quantity] = {
for
q
in
OptimadeStructureEntry
.
m_def
.
quantities
.
values
()
if
'elastic'
in
q
.
m_annotations
}
#for q in OptimadeStructureEntry.m_def.quantities.values():
# print(q.name, '-------------',q.m_annotations.keys(),'optimade' in q.m_annotations)
#print('IIIIIIIIIIIIIIIIIIIIIIIIIIII',type(quantities['elements']))
#raise
quantities
[
'elements'
].
length_quantity
=
quantities
[
'nelements'
]
quantities
[
'dimension_types'
].
length_quantity
=
quantities
[
'dimension_types'
]
quantities
[
'elements'
].
has_only_quantity
=
Quantity
(
name
=
'only_atoms'
)
quantities
[
'elements'
].
nested_quantity
=
quantities
[
'elements_ratios'
]
quantities
[
'elements_ratios'
].
nested_quantity
=
quantities
[
'elements_ratios'
]
_parser
=
LarkParser
(
version
=
(
0
,
10
,
0
))
_transformer
=
Transformer
(
quantities
=
quantities
.
values
())
...
...
nomad/app/optimade/models.py
View file @
9301b014
...
...
@@ -214,7 +214,7 @@ json_api_data_object_model = api.model('JsonApiDataObject', {
class
CalculationDataObject
:
def
__init__
(
self
,
search_entry_dict
:
Dict
[
str
,
Any
],
request_fields
:
Set
[
str
]
=
None
):
attrs
=
search_entry_dict
#
attrs = search_entry_dict
attrs
=
{
key
:
value
for
key
,
value
in
search_entry_dict
[
'optimade'
].
items
()
...
...
@@ -231,6 +231,9 @@ class CalculationDataObject:
self
.
type
=
'calculation'
self
.
id
=
search_entry_dict
[
'calc_id'
]
#attrs['immutable_id'] = search_entry_dict['calc_id']
#attrs['last_modified'] = search_entry_dict.get(
# 'last_processing', search_entry_dict.get('upload_time', None))
self
.
immutable_id
=
search_entry_dict
[
'calc_id'
]
self
.
last_modified
=
search_entry_dict
.
get
(
'last_processing'
,
search_entry_dict
.
get
(
'upload_time'
,
None
))
...
...
nomad/metainfo/optimade.py
View file @
9301b014
...
...
@@ -118,7 +118,8 @@ class OptimadeStructureEntry(MSection):
lattice_vectors
=
Quantity
(
type
=
np
.
dtype
(
'f8'
),
shape
=
[
3
,
3
],
unit
=
units
.
angstrom
,
links
=
optimade_links
(
'h.6.2.9'
),
a_optimade
=
Optimade
(
query
=
False
,
entry
=
True
),
#a_elastic=dict(type=Float),
a_optimade
=
Optimade
(
query
=
True
,
entry
=
True
),
description
=
'''
The three lattice vectors in Cartesian coordinates, in ångström (Å).
'''
)
...
...
@@ -126,6 +127,7 @@ class OptimadeStructureEntry(MSection):
cartesian_site_positions
=
Quantity
(
type
=
np
.
dtype
(
'f8'
),
shape
=
[
'nsites'
,
3
],
unit
=
units
.
angstrom
,
links
=
optimade_links
(
'h.6.2.10'
),
#a_elastic=dict(type=Float),
a_optimade
=
Optimade
(
query
=
False
,
entry
=
True
),
description
=
'''
Cartesian positions of each site. A site is an atom, a site potentially occupied by
an atom, or a placeholder for a virtual mixture of atoms (e.g., in a virtual crystal
...
...
nomad/normalizing/optimade.py
View file @
9301b014
...
...
@@ -20,6 +20,7 @@ from nomad.normalizing.normalizer import SystemBasedNormalizer
from
nomad.metainfo
import
units
from
nomad.metainfo.optimade
import
OptimadeStructureEntry
from
string
import
ascii_uppercase
class
OptimadeNormalizer
(
SystemBasedNormalizer
):
...
...
@@ -74,9 +75,12 @@ class OptimadeNormalizer(SystemBasedNormalizer):
optimade
.
chemical_formula_reduced
=
get_value
(
'chemical_composition_reduced'
)
optimade
.
chemical_formula_hill
=
get_value
(
'chemical_composition_bulk_reduced'
)
optimade
.
chemical_formula_descriptive
=
optimade
.
chemical_formula_hill
#optimade.chemical_formula_anonymous = ''.join([
# '%s' % element + (str(atom_counts[element]) if atom_counts[element] > 1 else '')
# for element in optimade.elements])
optimade
.
chemical_formula_anonymous
=
''
.
join
([
'%s'
%
element
+
(
str
(
atom_counts
[
element
])
if
atom_counts
[
element
]
>
1
else
''
)
for
element
in
optimade
.
elements
])
'%s'
%
ascii_uppercase
[
i
%
len
(
ascii_uppercase
)]
+
(
str
(
atom_counts
[
optimade
.
element
s
[
i
]
])
if
atom_counts
[
optimade
.
element
s
[
i
]
]
>
1
else
''
)
for
i
in
range
(
len
(
optimade
.
elements
))
])
# sites
optimade
.
nsites
=
len
(
nomad_species
)
...
...
@@ -92,6 +96,13 @@ class OptimadeNormalizer(SystemBasedNormalizer):
return
optimade
#AL
#def gen_species(self,elements):
# species = []
# for i in range(len(elements)):
# specie = {'name':'%s%d'%(elements[i])}
def
normalize_system
(
self
,
index
):
try
:
optimade
=
self
.
get_optimade_data
(
index
)
...
...
tests/app/test_optimade.py
View file @
9301b014
...
...
@@ -27,7 +27,7 @@ from nomad.app.optimade import parse_filter, url
from
tests.app.test_app
import
BlueprintClient
from
tests.test_normalizing
import
run_normalize
from
tests.conftest
import
clear_elastic
from
tests.utils
import
assert_exception
@
pytest
.
fixture
(
scope
=
'function'
)
def
api
(
client
):
...
...
@@ -36,12 +36,12 @@ def api(client):
def
test_get_entry
(
published
:
Upload
):
calc_id
=
list
(
published
.
calcs
)[
0
].
calc_id
with
published
.
upload_files
.
archive_file
(
calc_id
)
as
f
:
data
=
json
.
load
(
f
)
assert
'OptimadeStructureEntry'
in
data
search_result
=
search
.
SearchRequest
().
search_parameter
(
'calc_id'
,
calc_id
).
execute_paginated
()[
'results'
][
0
]
#print(search_result['optimade'].values())
#raise
assert
'optimade'
in
search_result
...
...
@@ -76,6 +76,7 @@ def create_test_structure(meta_info, id: int, h: int, o: int, extra: List[str],
@
pytest
.
fixture
(
scope
=
'module'
)
def
example_structures
(
meta_info
,
elastic_infra
):
print
(
'>>>>>>>>>>>>>>>>>>>>>>>>>>METAINFO'
,
meta_info
)
clear_elastic
(
elastic_infra
)
create_test_structure
(
meta_info
,
1
,
2
,
1
,
[],
0
)
create_test_structure
(
meta_info
,
2
,
2
,
1
,
[
'C'
],
0
)
...
...
@@ -103,6 +104,13 @@ def example_structures(meta_info, elastic_infra):
(
'elements HAS ANY "C"'
,
1
),
(
'elements HAS ONLY "C"'
,
0
),
(
'elements HAS ONLY "H", "O"'
,
3
),
#AL
(
'nelements >= 2 AND elements HAS ONLY "H", "O"'
,
3
),
(
'nelements >= 2 AND elements HAS ALL "H", "O", "C"'
,
1
),
(
'nelements >= 2 AND NOT elements HAS ALL "H", "O", "C"'
,
3
),
(
'NOT nelements = 2 AND elements HAS ANY "H", "O", "C"'
,
1
),
(
'NOT nelements = 3 AND NOT elements HAS ONLY "H", "O"'
,
0
),
#
(
'elements:elements_ratios HAS "H":>0.66'
,
2
),
(
'elements:elements_ratios HAS ALL "O":>0.33'
,
3
),
(
'elements:elements_ratios HAS ALL "O":>0.33,"O":<0.34'
,
2
),
...
...
@@ -116,6 +124,15 @@ def example_structures(meta_info, elastic_infra):
(
'chemical_formula_reduced STARTS WITH "H2"'
,
3
),
(
'chemical_formula_reduced ENDS WITH "C"'
,
1
),
(
'chemical_formula_reduced ENDS "C"'
,
1
),
#AL
(
'chemical_formula_hill CONTAINS "1"'
,
0
),
(
'chemical_formula_hill STARTS WITH "H" AND chemical_formula_hill ENDS WITH "O"'
,
3
),
(
'NOT chemical_formula_descriptive ENDS WITH "1"'
,
4
),
(
'chemical_formula_descriptive CONTAINS "C" AND NOT chemical_formula_descriptive STARTS WITH "O"'
,
1
),
(
'NOT chemical_formula_anonymous STARTS WITH "A"'
,
0
),
(
'chemical_formula_anonymous CONTAINS "AB2" AND chemical_formula_anonymous ENDS WITH "C"'
,
1
),
(
'nsites >=3 AND LENGTH elements = 2'
,
2
),
#
(
'LENGTH elements = 2'
,
3
),
(
'LENGTH elements = 3'
,
1
),
(
'LENGTH dimension_types = 0'
,
3
),
...
...
@@ -125,48 +142,74 @@ def example_structures(meta_info, elastic_infra):
(
'nelements = 3 OR LENGTH dimension_types = 1'
,
2
),
(
'nelements > 1 OR LENGTH dimension_types = 1 AND nelements = 2'
,
4
),
(
'(nelements > 1 OR LENGTH dimension_types = 1) AND nelements = 2'
,
3
),
(
'NOT LENGTH dimension_types = 1'
,
3
)
(
'NOT LENGTH dimension_types = 1'
,
3
),
#AL
(
'LENGTH nelements = 1'
,
-
1
),
(
'chemical_formula_anonymous starts with "A"'
,
-
1
),
(
'elements HAS ONY "H", "O"'
,
-
1
)
# ('elements > 3', -1),
# ('chemical_formula_hill HAS "C"', -1)
])
def
test_optimade_parser
(
example_structures
,
query
,
results
):
query
=
parse_filter
(
query
)
result
=
search
.
SearchRequest
(
query
=
query
).
execute_paginated
()
assert
result
[
'pagination'
][
'total'
]
==
results
if
results
>=
0
:
query
=
parse_filter
(
query
)
result
=
search
.
SearchRequest
(
query
=
query
).
execute_paginated
()
assert
result
[
'pagination'
][
'total'
]
==
results
else
:
with
assert_exception
():
query
=
parse_filter
(
query
)
#result = search.SearchRequest(query=query).execute_paginated()
def
test_url
():
assert
url
(
'endpoint'
,
param
=
'value'
).
endswith
(
'/optimade/endpoint?param=value'
)
def
test_list_endpoint
(
api
,
example_structures
):
rv
=
api
.
get
(
'/calculations'
)
assert
rv
.
status_code
==
200
data
=
json
.
loads
(
rv
.
data
)
#AL
for
entry
in
[
'data'
,
'links'
,
'meta'
]:
assert
entry
in
data
assert
len
(
data
[
'data'
])
==
4
# TODO replace with real assertions
#
print(json.dumps(data, indent=2))
print
(
json
.
dumps
(
data
,
indent
=
2
))
raise
def
test_list_endpoint_request_fields
(
api
,
example_structures
):
rv
=
api
.
get
(
'/calculations?request_fields=nelements,elements'
)
assert
rv
.
status_code
==
200
data
=
json
.
loads
(
rv
.
data
)
#print('-----------------------',data['data'][1]['attributes'].keys())
# TODO replace with real assertions
# print(json.dumps(data, indent=2))
#print(json.dumps(data, indent=2))
for
i
in
range
(
4
):
rf
=
list
(
data
[
'data'
][
i
][
'attributes'
].
keys
())
rf
.
sort
()
assert
rf
==
[
'elements'
,
'nelements'
]
def
test_single_endpoint
(
api
,
example_structures
):
rv
=
api
.
get
(
'/calculations/%s'
%
'test_calc_id_1'
)
assert
rv
.
status_code
==
200
data
=
json
.
loads
(
rv
.
data
)
# TODO replace with real assertions
# print(json.dumps(data, indent=2))
for
key
in
[
'type'
,
'id'
,
'attributes'
]:
assert
key
in
data
[
'data'
]
#print('-----------------------',data['data'].keys())
#print(json.dumps(data, indent=2))
def
test_base_info_endpoint
(
api
):
rv
=
api
.
get
(
'/info'
)
assert
rv
.
status_code
==
200
data
=
json
.
loads
(
rv
.
data
)
print
(
'-----------------------'
,
data
.
keys
())
# TODO replace with real assertions
# print(json.dumps(data, indent=2))
for
key
in
[
'type'
,
'id'
,
'attributes'
]:
assert
key
in
data
[
'data'
]
assert
data
[
'data'
][
'type'
]
==
'info'
assert
data
[
'data'
][
'id'
]
==
'/'
#assert 'meta' in data
#print(json.dumps(data, indent=2))
def
test_calculation_info_endpoint
(
api
):
...
...
@@ -174,7 +217,7 @@ def test_calculation_info_endpoint(api):
assert
rv
.
status_code
==
200
data
=
json
.
loads
(
rv
.
data
)
# TODO replace with real assertions
#
print(json.dumps(data, indent=2))
#print(json.dumps(data, indent=2))
# TODO test single with request_fields
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment