Ejemplo n.º 1
0
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]
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
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(
            ' ', '&nbsp;')

        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(' ', '&nbsp;')
    qe_matdyn = str(jinja2.escape(get_qe_matdyn(
        raw_code_dict, out_json_data))).replace('\n',
                                                '<br>').replace(' ', '&nbsp;')
    cp2k = str(jinja2.escape(get_cp2k(raw_code_dict))).replace(
        '\n', '<br>').replace(' ', '&nbsp;')

    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 ""),
    )