def test(format, file): click.echo("Format: {}".format(format)) structure = structure_importers.get_structure_tuple(file, format, extra_data=None) print "# CELL" for v in structure[0]: print v print "# COORDINATES" for coords in structure[1]: print coords print "# ATOM TYPE IDX" print structure[2]
def test_correct_file_examples(self): """Check if these valid structures are properly parsed""" with open(os.path.join(this_folder, 'file_examples', 'list.json')) as f: list_files = json.load(f) for the_format, examples in list_files.items(): for example in examples: filename = example['file'] extra_data = example.get('extra_data', None) with open(os.path.join(this_folder, 'file_examples', filename)) as f: structure = structure_importers.get_structure_tuple( f, the_format, extra_data=extra_data) seekpath_results = seekpath.get_path(structure)
def test_wrong_file_examples(self): """Check if these valid structures are properly parsed""" with open(os.path.join(this_folder, 'file_examples_wrong', 'list.json')) as f: list_files = json.load(f) for the_format, examples in list_files.items(): for example in examples: filename = example['file'] extra_data = example.get('extra_data', None) with open( os.path.join(this_folder, 'file_examples_wrong', filename)) as f: # The error I get is generic, so for now I just check if it crashes with self.assertRaises(Exception): structure = structure_importers.get_structure_tuple( f, the_format, extra_data=extra_data)
def test_failing_file_examples(self): """These should be files that are valid in format but invalid when looking for symmetry""" with open( os.path.join(this_folder, 'file_examples_failing', 'list.json')) as f: list_files = json.load(f) for the_format, examples in list_files.items(): for example in examples: filename = example['file'] extra_data = example.get('extra_data', None) with open( os.path.join(this_folder, 'file_examples_failing', filename)) as f: structure = structure_importers.get_structure_tuple( f, the_format, extra_data=extra_data) # No additional check, just check if it works with self.assertRaises(SymmetryDetectionError): seekpath_results = seekpath.get_path(structure)
def process_structure_core(filecontent, fileformat, seekpath_module, call_source="", logger=None, flask_request=None): """ The main function that generates the data to be sent back to the view. :param filecontent: The file content (string) :param fileformat: The file format (string), among the accepted formats :param seekpath_module: the seekpath module. The reason for passing it is that, when running in debug mode, you want to get the local seekpath rather than the installed one. :param call_source: a string identifying the source (i.e., who called this function). This is a string, mainly for logging reasons. :param logger: if not None, should be a valid logger, that is used to output useful log messages. :param flask_request: if logger is not None, pass also the flask.request object to help in logging. :return: this function calls directly flask methods and returns flask objects :raise: FlaskRedirectException if there is an error that requires to redirect the the main selection page. The Exception message is the message to be flashed via Flask (or in general shown to the user). """ from structure_importers import get_structure_tuple, UnknownFormatError start_time = time.time() fileobject = io.StringIO(str(filecontent)) form_data = dict(flask_request.form) try: structure_tuple = get_structure_tuple(fileobject, fileformat, extra_data=form_data) except UnknownFormatError: logme(logger, filecontent, fileformat, flask_request, call_source, reason='unknownformat', extra={ 'form_data': form_data, }) raise FlaskRedirectException("Unknown format '{}'".format(fileformat)) except Exception: # There was an exception... import traceback logme(logger, filecontent, fileformat, flask_request, call_source, reason='exception', extra={ 'traceback': traceback.format_exc(), 'form_data': form_data, }) raise FlaskRedirectException( "I tried my best, but I wasn't able to load your " "file in format '{}'...".format(fileformat)) if len(structure_tuple[1]) > MAX_NUMBER_OF_ATOMS: ## Structure too big logme(logger, filecontent, fileformat, flask_request, call_source, reason='toolarge', extra={ 'number_of_atoms': len(structure_tuple[1]), 'form_data': form_data, }) raise FlaskRedirectException( "Sorry, this online visualizer is limited to {} atoms " "in the input cell, while your structure has {} atoms." "".format(MAX_NUMBER_OF_ATOMS, len(structure_tuple[1]))) # Log the content in case of valid structure logme(logger, filecontent, fileformat, flask_request, call_source, reason='OK', extra={ 'number_of_atoms': len(structure_tuple[1]), 'form_data': form_data, }) try: in_json_data = { 'cell': structure_tuple[0], 'scaled_coords': structure_tuple[1], 'atomic_numbers': structure_tuple[2] } out_json_data, path_results = get_json_for_visualizer( in_json_data['cell'], in_json_data['scaled_coords'], in_json_data['atomic_numbers'], seekpath_module=seekpath_module) raw_code_dict = copy.copy(out_json_data) for k in list(raw_code_dict.keys()): if k.startswith('explicit_'): raw_code_dict.pop(k) if k == 'segments': raw_code_dict.pop(k) raw_code_dict.pop('faces_data') raw_code_dict['primitive_lattice'] = path_results[ 'primitive_lattice'].tolist() raw_code_dict['primitive_positions'] = path_results[ 'primitive_positions'].tolist() inputstructure_positions_cartesian = np.dot( np.array(in_json_data['scaled_coords']), np.array(in_json_data['cell']), ).tolist() primitive_positions_cartesian = np.dot( np.array(path_results['primitive_positions']), np.array(path_results['primitive_lattice']), ).tolist() primitive_positions_cartesian_refolded = np.dot( np.array(path_results['primitive_positions']) % 1., np.array(path_results['primitive_lattice']), ).tolist() raw_code_dict['primitive_positions_cartesian'] = \ primitive_positions_cartesian # raw_code['primitive_types'] = path_results['primitive_types'] primitive_symbols = [ chemical_symbols[num] for num in path_results['primitive_types'] ] raw_code_dict['primitive_symbols'] = primitive_symbols raw_code = json.dumps(raw_code_dict, indent=2) ## I manually escape it to then add <br> and pass it to a filter with ## |safe. I have to 'unicode' it otherwise it keeps escaping also the ## next replaces raw_code = str(jinja2.escape(raw_code)).replace('\n', '<br>').replace( ' ', ' ') kpoints = [[ k, out_json_data['kpoints'][k][0], out_json_data['kpoints'][k][1], out_json_data['kpoints'][k][2] ] for k in sorted(out_json_data['kpoints'])] kpoints_rel = [[ k, out_json_data['kpoints_rel'][k][0], out_json_data['kpoints_rel'][k][1], out_json_data['kpoints_rel'][k][2] ] for k in sorted(out_json_data['kpoints_rel'])] inputstructure_cell_vectors = [[ idx, coords[0], coords[1], coords[2] ] for idx, coords in enumerate(in_json_data['cell'], start=1)] inputstructure_symbols = [ chemical_symbols[num] for num in in_json_data['atomic_numbers'] ] inputstructure_atoms_scaled = [[ label, coords[0], coords[1], coords[2] ] for label, coords in zip(inputstructure_symbols, in_json_data['scaled_coords'])] inputstructure_atoms_cartesian = [[ label, coords[0], coords[1], coords[2] ] for label, coords in zip(inputstructure_symbols, inputstructure_positions_cartesian)] direct_vectors = [[idx, coords[0], coords[1], coords[2]] for idx, coords in enumerate( path_results['primitive_lattice'], start=1)] reciprocal_primitive_vectors = [[ idx, coords[0], coords[1], coords[2] ] for idx, coords in enumerate( path_results['reciprocal_primitive_lattice'], start=1)] atoms_scaled = [ [label, coords[0], coords[1], coords[2]] for label, coords in zip( primitive_symbols, path_results['primitive_positions']) ] atoms_cartesian = [ [label, coords[0], coords[1], coords[2]] for label, coords in zip( primitive_symbols, primitive_positions_cartesian) ] # Create extetically-nice looking path, with dashes and pipes suggested_path = [] if path_results['path']: suggested_path.append(path_results['path'][0][0]) suggested_path.append('-') suggested_path.append(path_results['path'][0][1]) last = path_results['path'][0][1] for p1, p2 in path_results['path'][1:]: if p1 != last: suggested_path.append('|') suggested_path.append(p1) suggested_path.append('-') suggested_path.append(p2) last = p2 primitive_lattice = path_results['primitive_lattice'] # Manual recenter of the structure center = (primitive_lattice[0] + primitive_lattice[1] + primitive_lattice[2]) / 2. cell_json = { "t": "UnitCell", "i": "s0", "o": (-center).tolist(), "x": (primitive_lattice[0] - center).tolist(), "y": (primitive_lattice[1] - center).tolist(), "z": (primitive_lattice[2] - center).tolist(), "xy": (primitive_lattice[0] + primitive_lattice[1] - center).tolist(), "xz": (primitive_lattice[0] + primitive_lattice[2] - center).tolist(), "yz": (primitive_lattice[1] + primitive_lattice[2] - center).tolist(), "xyz": (primitive_lattice[0] + primitive_lattice[1] + primitive_lattice[2] - center).tolist(), } atoms_json = [{ "l": label, "x": pos[0] - center[0], "y": pos[1] - center[1], "z": pos[2] - center[2] } for label, pos in zip(primitive_symbols, primitive_positions_cartesian_refolded)] # These will be passed to ChemDoodle json_content = {"s": [cell_json], "m": [{"a": atoms_json}]} compute_time = time.time() - start_time except Exception: import traceback logme(logger, filecontent, fileformat, flask_request, call_source, reason='codeexception', extra={ 'traceback': traceback.extract_stack(), 'form_data': form_data, }) raise qe_pw = str(jinja2.escape(get_qe_pw( raw_code_dict, out_json_data))).replace('\n', '<br>').replace(' ', ' ') qe_matdyn = str(jinja2.escape(get_qe_matdyn( raw_code_dict, out_json_data))).replace('\n', '<br>').replace(' ', ' ') cp2k = str(jinja2.escape(get_cp2k(raw_code_dict))).replace( '\n', '<br>').replace(' ', ' ') return dict( jsondata=json.dumps(out_json_data), json_content=json.dumps(json_content), volume_ratio_prim=int(round(path_results['volume_original_wrt_prim'])), raw_code=raw_code, kpoints=kpoints, kpoints_rel=kpoints_rel, bravais_lattice=path_results['bravais_lattice'], bravais_lattice_extended=path_results['bravais_lattice_extended'], spacegroup_number=path_results['spacegroup_number'], spacegroup_international=path_results['spacegroup_international'], direct_vectors=direct_vectors, inputstructure_cell_vectors=inputstructure_cell_vectors, inputstructure_atoms_scaled=inputstructure_atoms_scaled, inputstructure_atoms_cartesian=inputstructure_atoms_cartesian, atoms_scaled=atoms_scaled, with_without_time_reversal=( "with" if path_results['has_inversion_symmetry'] else "without"), atoms_cartesian=atoms_cartesian, reciprocal_primitive_vectors=reciprocal_primitive_vectors, suggested_path=suggested_path, qe_pw=qe_pw, qe_matdyn=qe_matdyn, cp2k=cp2k, compute_time=compute_time, seekpath_version=seekpath_module.__version__, spglib_version=spglib.__version__, time_reversal_note=(time_reversal_note if path_results['augmented_path'] else ""), )