Skip to content
This repository was archived by the owner on Jul 20, 2025. It is now read-only.

Commit 8d01f10

Browse files
committed
Add docstrings, new design by similarity code and design metrics
1 parent f2b2322 commit 8d01f10

File tree

1 file changed

+70
-20
lines changed

1 file changed

+70
-20
lines changed

mpds_ml_labs/app.py

Lines changed: 70 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11

22
import os, sys
3-
import random
43

54
import ujson as json
65

@@ -10,9 +9,9 @@
109
from cif_utils import cif_to_ase, ase_to_eq_cif
1110
from prediction import prop_models, get_prediction, get_aligned_descriptor, get_ordered_descriptor, get_legend, load_ml_models
1211
from common import SERVE_UI, ML_MODELS, connect_database
13-
1412
from knn_sample import knn_sample
15-
from local_mpds import materialize, score
13+
from similar_els import materialize, score
14+
from prediction_ranges import TOL_QUALITY
1615

1716

1817
app_labs = Blueprint('app_labs', __name__)
@@ -45,22 +44,42 @@ def html_formula(string):
4544

4645
if SERVE_UI:
4746
@app_labs.route('/', methods=['GET'])
47+
@app_labs.route('/props.html', methods=['GET'])
4848
def index():
49-
return send_from_directory(static_path, 'index.html')
50-
@app_labs.route('/index.css', methods=['GET'])
51-
def style():
52-
return send_from_directory(static_path, 'index.css')
49+
return send_from_directory(static_path, 'props.html')
50+
51+
@app_labs.route('/common.css', methods=['GET'])
52+
def css():
53+
return send_from_directory(static_path, 'common.css')
54+
5355
@app_labs.route('/player.html', methods=['GET'])
5456
def player():
5557
return send_from_directory(static_path, 'player.html')
5658

59+
@app_labs.route('/design.html', methods=['GET'])
60+
def md():
61+
return send_from_directory(static_path, 'design.html')
62+
63+
@app_labs.route('/jquery.min.js', methods=['GET'])
64+
def jquery():
65+
return send_from_directory(static_path, 'jquery.min.js')
66+
67+
@app_labs.route('/nouislider.min.js', methods=['GET'])
68+
def nouislider():
69+
return send_from_directory(static_path, 'nouislider.min.js')
70+
5771
@app_labs.after_request
5872
def add_cors_header(response):
5973
response.headers['Access-Control-Allow-Origin'] = '*'
6074
return response
6175

6276
@app_labs.route("/predict", methods=['POST'])
6377
def predict():
78+
"""
79+
A main endpoint for the properties
80+
prediction, based on the provided CIF
81+
or POSCAR
82+
"""
6483
if 'structure' not in request.values:
6584
return fmt_msg('Invalid request')
6685

@@ -122,19 +141,30 @@ def predict():
122141

123142
@app_labs.route("/download_cif", methods=['POST'])
124143
def download_cif():
125-
if 'structure' not in request.values:
144+
"""
145+
An utility endpoint to force
146+
a browser file (CIF) download
147+
"""
148+
structure = request.values.get('structure')
149+
title = request.values.get('title')
150+
151+
if not structure or not title:
126152
return fmt_msg('Invalid request')
127153

128-
structure = request.values.get('structure')
129-
if not 0 < len(structure) < 32768:
154+
if not 0 < len(structure) < 100000:
130155
return fmt_msg('Request size is invalid')
131156

132157
return Response(structure, mimetype="chemical/x-cif", headers={
133-
"Content-Disposition": "attachment;filename=%s.cif" % random.randint(10000, 99999)
158+
"Content-Disposition": "attachment;filename=%s.cif" % title
134159
})
135160

136161
@app_labs.route("/design", methods=['POST'])
137162
def design():
163+
"""
164+
A main endpoint for generating
165+
the CIF structure based on
166+
the provided values of the properties
167+
"""
138168
if 'numerics' not in request.values:
139169
return fmt_msg('Invalid request')
140170

@@ -144,31 +174,31 @@ def design():
144174
if type(numerics) != dict:
145175
return fmt_msg('Invalid request')
146176

147-
prop_ranges_dict = {}
177+
user_ranges_dict = {}
148178

149179
for prop_id in prop_models:
150180
if prop_id not in numerics or type(numerics[prop_id]) != list or len(numerics[prop_id]) != 2:
151181
return fmt_msg('Invalid request')
152-
try: prop_ranges_dict[prop_id + '_min'], prop_ranges_dict[prop_id + '_max'] = float(numerics[prop_id][0]), float(numerics[prop_id][1])
182+
try: user_ranges_dict[prop_id + '_min'], user_ranges_dict[prop_id + '_max'] = float(numerics[prop_id][0]), float(numerics[prop_id][1])
153183
except:
154184
return fmt_msg('Invalid request')
155185

156-
if prop_ranges_dict['w_min'] == 0 and prop_ranges_dict['w_max'] == 0:
157-
prop_ranges_dict['w_min'], prop_ranges_dict['w_max'] = -100, 100 # NB. any band gap is allowed
186+
if user_ranges_dict['w_min'] == 0 and user_ranges_dict['w_max'] == 0:
187+
user_ranges_dict['w_min'], user_ranges_dict['w_max'] = -100, 100 # NB. any band gap is allowed
158188

159189
cursor, connection = connect_database()
160190

161191
result, error = None, "No results (outside of prediction capabilities)"
162192

163-
els_samples = knn_sample(cursor, prop_ranges_dict)
193+
els_samples = knn_sample(cursor, user_ranges_dict)
164194
for els_sample in els_samples:
165195
#print "TRYING TO MATERIALIZE", ", ".join(els_sample)
166196

167-
scoring, error = materialize(cursor, els_sample, active_ml_models)
197+
scoring, error = materialize(els_sample, active_ml_models)
168198
if error or not scoring:
169199
continue
170200

171-
result = score(scoring, prop_ranges_dict)
201+
result = score(scoring, user_ranges_dict)
172202
break
173203

174204
connection.close()
@@ -182,11 +212,31 @@ def design():
182212
if error: return fmt_msg(error)
183213
result['structure'].center(about=0.0)
184214

215+
formula = get_formula(result['structure'])
216+
217+
result_quality, aux_info = 0, []
218+
for k, v in answer_props.items():
219+
aux_info.append([
220+
prop_models[k]['name'].replace(' ', '_'),
221+
sample[k + '_min'],
222+
v,
223+
sample[k + '_max'],
224+
prop_models[k]['units']
225+
])
226+
tol = (sample[k + '_max'] - sample[k + '_min']) * TOL_QUALITY
227+
if sample[k + '_min'] - tol < v < sample[k + '_max'] + tol:
228+
result_quality += 1
229+
185230
return Response(
186231
json.dumps({
187-
'vis_cif': ase_to_eq_cif(result['structure'], supply_sg=False),
232+
'vis_cif': ase_to_eq_cif(
233+
result['structure'],
234+
supply_sg=False,
235+
mpds_labs_loop=[result_quality] + aux_info
236+
),
188237
'props': answer_props,
189-
'formula': html_formula(get_formula(result['structure'])),
238+
'formula': html_formula(formula),
239+
'title': formula
190240
}, indent=4, escape_forward_slashes=False
191241
),
192242
content_type='application/json'

0 commit comments

Comments
 (0)