コード例 #1
0
ファイル: analysis.py プロジェクト: apayne9/PyChemia
 def fp_oganov(self, delta=0.01, sigma=0.01):
     struc_dist_x, struc_dist = self.structure_distances(delta=delta, sigma=sigma)
     fp_oganov = struc_dist.copy()
     vol = self.structure.volume
     for spec_pair in struc_dist:
         for i in range(len(struc_dist[spec_pair])):
             specie0 = atomic_symbol(spec_pair[0])
             specie1 = atomic_symbol(spec_pair[1])
             number_atoms0 = self.structure.composition[specie0]
             number_atoms1 = self.structure.composition[specie1]
             fp_oganov[spec_pair][i] *= vol / (delta * number_atoms0 * number_atoms1)
             fp_oganov[spec_pair][i] -= 1
     return struc_dist_x, fp_oganov
コード例 #2
0
ファイル: analysis.py プロジェクト: wwmeng/PyChemia
 def fp_oganov(self, delta=0.01, sigma=0.01):
     struc_dist_x, struc_dist = self.structure_distances(delta=delta,
                                                         sigma=sigma)
     fp_oganov = struc_dist.copy()
     vol = self.structure.volume
     for spec_pair in struc_dist:
         for i in range(len(struc_dist[spec_pair])):
             specie0 = atomic_symbol(spec_pair[0])
             specie1 = atomic_symbol(spec_pair[1])
             number_atoms0 = self.structure.composition[specie0]
             number_atoms1 = self.structure.composition[specie1]
             fp_oganov[spec_pair][i] *= vol / (delta * number_atoms0 *
                                               number_atoms1)
             fp_oganov[spec_pair][i] -= 1
     return struc_dist_x, fp_oganov
コード例 #3
0
ファイル: input.py プロジェクト: kvlvn/PyChemia
def xyz2input(filename):
    """
    Reads a .xyz and return an ABINIT input
    as a python dictionary
    """

    abiinput = AbinitInput()
    atomdict = atomic_symbol()
    rf = open(filename, 'r')

    natom = int(rf.readline())
    typat = []
    znucl = []
    xangst = []

    ntypat = 0
    rf.readline()
    data = rf.readlines()
    for i in range(natom):
        atom = data[i].split()
        atomnumber = atomdict[atom[0]]
        if atomnumber not in znucl:
            ntypat += 1
            znucl.append(atomnumber)
        typat.append(znucl.index(atomnumber) + 1)
        xangst += [float(atom[1]), float(atom[2]), float(atom[3])]

    abiinput.variables['natom'] = np.array([natom])
    abiinput.variables['znucl'] = np.array(znucl)
    abiinput.variables['ntypat'] = np.array([ntypat])
    abiinput.variables['typat'] = np.array(typat)
    abiinput.variables['xcart'] = angstrom_bohr * np.array(xangst)

    return abiinput
コード例 #4
0
ファイル: input.py プロジェクト: MaterialsDiscovery/PyChemia
def xyz2input(filename):
    """
    Reads a .xyz and return an ABINIT input
    as a python dictionary
    """

    abiinput = AbinitInput()
    atomdict = atomic_symbol()
    rf = open(filename, 'r')

    natom = int(rf.readline())
    typat = []
    znucl = []
    xangst = []

    ntypat = 0
    rf.readline()
    data = rf.readlines()
    for i in range(natom):
        atom = data[i].split()
        atomnumber = atomdict[atom[0]]
        if atomnumber not in znucl:
            ntypat += 1
            znucl.append(atomnumber)
        typat.append(znucl.index(atomnumber) + 1)
        xangst += [float(atom[1]), float(atom[2]), float(atom[3])]

    abiinput.variables['natom'] = np.array([natom])
    abiinput.variables['znucl'] = np.array(znucl)
    abiinput.variables['ntypat'] = np.array([ntypat])
    abiinput.variables['typat'] = np.array(typat)
    abiinput.variables['xcart'] = angstrom_bohr * np.array(xangst)

    return abiinput
コード例 #5
0
def run_one(a):
    """
    Take one OQMD 'Entry' object, search all the calculations associated and take the best calculation
    in order to insert its data into the PyChemia Database

    :param a: OQMD Entry object
    :return:
    """
    print('Entry: %6d  Number of Calculations: %3d  Energies: %s' %
          (a.id, a.calculation_set.count(),
           str([c.energy for c in a.calculation_set.all()])))
    energy = 1E10
    best_calculation = None
    for c in a.calculation_set.all():
        if c.energy is not None and c.energy < energy:
            best_calculation = c
            energy = c.energy

    if best_calculation is None:
        return None, None

    cell = best_calculation.output.cell.T
    symbols = atomic_symbol(best_calculation.output.atomic_numbers)
    reduced = best_calculation.output.coords

    structure = pychemia.Structure(cell=cell, symbols=symbols, reduced=reduced)
    structure_id = best_calculation.output_id
    entry_id = a.id
    calculation_id = best_calculation.id
    energy_pa = best_calculation.energy_pa
    energy = best_calculation.energy
    band_gap = best_calculation.band_gap
    settings = best_calculation.settings
    try:
        spacegroup_number = best_calculation.output.spacegroup.number
    except ValueError:
        spacegroup_number = None

    symm = pychemia.crystal.CrystalSymmetry(structure)
    sym2 = symm.number(1E-2)

    properties = {
        'oqmd': {
            'structure_id': structure_id,
            'entry_id': entry_id,
            'calculation_id': calculation_id,
            'energy_pa': energy_pa,
            'energy': energy,
            'band_gap': band_gap,
            'settings': settings,
            'spacegroup_number': spacegroup_number
        },
        'spacegroup_number': {
            'value': sym2,
            'symprec': 1E-2
        }
    }

    return structure, properties
コード例 #6
0
 def atom_name(self, iatom, idtset=''):
     """
     Return the name of the atom and the position in the
     list of atoms such as H3, N4, etc
     """
     atomnumber = self.get_value('znucl', idtset=idtset)
     if isinstance(atomnumber, list):
         atomnumber = atomnumber[self.get_value('typat', idtset=idtset)[iatom] - 1]
     return atomic_symbol(atomnumber) + str(iatom + 1)
コード例 #7
0
ファイル: input.py プロジェクト: apayne9/PyChemia
 def atom_name(self, iatom, idtset=''):
     """
     Return the name of the atom and the position in the
     list of atoms such as H3, N4, etc
     """
     atomnumber = self.get_value('znucl', idtset=idtset)
     if isinstance(atomnumber, list):
         atomnumber = atomnumber[self.get_value('typat', idtset=idtset)[iatom] - 1]
     return atomic_symbol(atomnumber) + str(iatom + 1)
コード例 #8
0
ファイル: xyz.py プロジェクト: MaterialsDiscovery/PyChemia
def load(filename):
    symbols = loadtxt(filename, skiprows=2, usecols=[0], dtype='|S2', ndmin=1)
    symbols = [x.decode('utf-8') for x in symbols]

    for i in range(len(symbols)):
        if symbols[i].isdigit():
            symbols[i] = atomic_symbol(int(symbols[i]))

    positions = loadtxt(filename, skiprows=2, usecols=(1, 2, 3), ndmin=2)
    natom = len(symbols)
    periodicity = 3 * [False]
    return Structure(symbols=symbols, positions=positions, periodicity=periodicity, natom=natom)
コード例 #9
0
ファイル: fireball.py プロジェクト: ssthurai/PyChemia
def read_geometry_bas(filename):
    rf = open(filename, 'r')

    natom = int(rf.readline())
    symbols = []
    positions = np.zeros((natom, 3))

    for i in range(natom):
        line = rf.readline().split()
        symbols.append(atomic_symbol(int(line[0])))
        positions[i] = np.array(line[1:])

    return Structure(symbols=symbols, positions=positions, periodicity=False)
コード例 #10
0
def read_geometry_bas(filename):
    rf = open(filename, 'r')

    natom = int(rf.readline())
    symbols = []
    positions = np.zeros((natom, 3))

    for i in range(natom):
        line = rf.readline().split()
        symbols.append(atomic_symbol(int(line[0])))
        positions[i] = np.array(line[1:])

    return Structure(symbols=symbols, positions=positions, periodicity=False)
コード例 #11
0
ファイル: OQMD2PyChemia.py プロジェクト: guilleaf/PyChemia
def run_one(a):
    """
    Take one OQMD 'Entry' object, search all the calculations associated and take the best calculation
    in order to insert its data into the PyChemia Database

    :param a: OQMD Entry object
    :return:
    """
    print('Entry: %6d  Number of Calculations: %3d  Energies: %s' % (a.id, a.calculation_set.count(),
                                                                     str([c.energy for c in a.calculation_set.all()])))
    energy = 1E10
    best_calculation = None
    for c in a.calculation_set.all():
        if c.energy is not None and c.energy < energy:
            best_calculation = c
            energy = c.energy

    if best_calculation is None:
        return None, None

    cell = best_calculation.output.cell.T
    symbols = atomic_symbol(best_calculation.output.atomic_numbers)
    reduced = best_calculation.output.coords

    structure = pychemia.Structure(cell=cell, symbols=symbols, reduced=reduced)
    structure_id = best_calculation.output_id
    entry_id = a.id
    calculation_id = best_calculation.id
    energy_pa = best_calculation.energy_pa
    energy = best_calculation.energy
    band_gap = best_calculation.band_gap
    settings = best_calculation.settings
    try:
        spacegroup_number = best_calculation.output.spacegroup.number
    except ValueError:
        spacegroup_number = None

    symm = pychemia.symm.StructureSymmetry(structure)
    sym2 = symm.number(1E-2)

    properties = {'oqmd': {'structure_id': structure_id,
                           'entry_id': entry_id,
                           'calculation_id': calculation_id,
                           'energy_pa': energy_pa,
                           'energy': energy,
                           'band_gap': band_gap,
                           'settings': settings,
                           'spacegroup_number': spacegroup_number},
                  'spacegroup_number': {'value': sym2, 'symprec': 1E-2}}

    return structure, properties
コード例 #12
0
ファイル: xyz.py プロジェクト: yw-fang/PyChemia
def load(filename):
    symbols = loadtxt(filename, skiprows=2, usecols=[0], dtype='|S2', ndmin=1)
    symbols = [x.decode('utf-8') for x in symbols]

    for i in range(len(symbols)):
        if symbols[i].isdigit():
            symbols[i] = atomic_symbol(int(symbols[i]))

    positions = loadtxt(filename, skiprows=2, usecols=(1, 2, 3), ndmin=2)
    natom = len(symbols)
    periodicity = 3 * [False]
    return Structure(symbols=symbols,
                     positions=positions,
                     periodicity=periodicity,
                     natom=natom)
コード例 #13
0
ファイル: utils.py プロジェクト: wwmeng/PyChemia
def psp_name(atomicnumber, exchange, kind):
    """
    Return the filename of a certain PSP given the
    atomic number, exchange ('LDA' or 'GGA')
    and kind ('FHI','TM')

    :param atomicnumber: (int) Atomic number
    :param exchange: (str) 'LDA' or 'GGA'
    :param kind: (str) Source of Pseudopotentials
    :return:
    """
    atom_symbol = str(atomic_symbol(atomicnumber))
    if kind == 'FHI' and exchange == 'LDA':
        filename = str(atomicnumber).zfill(2) + '-' + atom_symbol + '.LDA.fhi'
    elif kind == 'FHI' and exchange == 'GGA':
        filename = str(atomicnumber).zfill(2) + '-' + atom_symbol + '.GGA.fhi'
    elif kind == 'CORE' and exchange == 'LDA':
        filename = str(atomicnumber) + atom_symbol.lower() + '.1s_psp.mod'
    elif kind == 'GTH' and exchange == 'LDA':
        filename = str(atomicnumber).zfill(2) + atom_symbol.lower() + '.pspgth'
    elif kind == 'TM' and exchange == 'LDA':
        filename = str(atomicnumber) + atom_symbol.lower() + '.pspnc'
    elif kind == 'AE' and exchange == 'DEN':
        filename = '0.' + str(atomicnumber).zfill(
            2) + '-' + atom_symbol + '.8.density.AE'
    elif kind == 'FC' and exchange == 'DEN':
        filename = str(atomicnumber).zfill(2) + '-' + atom_symbol + '.8.fc'
    elif kind == 'PAW' and exchange == 'GGA':
        filename = 'JTH-PBE-atomicdata-0.2/' + atom_symbol + '.GGA_PBE-JTH.xml'
    elif kind == 'PAW' and exchange == 'LDA':
        filename = 'JTH-LDA-atomicdata-0.2/' + atom_symbol + '.LDA_PW-JTH.xml'
    elif kind == 'HGH' and exchange == 'GGA':
        filename = str(atomicnumber).zfill(
            2) + atom_symbol.lower() + '.pbe_hgh'
    elif kind == 'ONC' and exchange == 'PBE':
        filename = 'pbe_s_sr' + os.sep + atom_symbol + '.psp8'
    else:
        print('The combination of exchange=%s and kind=%s is not known' %
              (exchange, kind))
        filename = ''
    return filename
コード例 #14
0
ファイル: utils.py プロジェクト: MaterialsDiscovery/PyChemia
def psp_name(atomicnumber, exchange, kind):
    """
    Return the filename of a certain PSP given the
    atomic number, exchange ('LDA' or 'GGA')
    and kind ('FHI','TM')

    :param atomicnumber: (int) Atomic number
    :param exchange: (str) 'LDA' or 'GGA'
    :param kind: (str) Source of Pseudopotentials
    :return:
    """
    atom_symbol = str(atomic_symbol(atomicnumber))
    if kind == 'FHI' and exchange == 'LDA':
        filename = str(atomicnumber).zfill(2) + '-' + atom_symbol + '.LDA.fhi'
    elif kind == 'FHI' and exchange == 'GGA':
        filename = str(atomicnumber).zfill(2) + '-' + atom_symbol + '.GGA.fhi'
    elif kind == 'CORE' and exchange == 'LDA':
        filename = str(atomicnumber) + atom_symbol.lower() + '.1s_psp.mod'
    elif kind == 'GTH' and exchange == 'LDA':
        filename = str(atomicnumber).zfill(2) + atom_symbol.lower() + '.pspgth'
    elif kind == 'TM' and exchange == 'LDA':
        filename = str(atomicnumber) + atom_symbol.lower() + '.pspnc'
    elif kind == 'AE' and exchange == 'DEN':
        filename = '0.' + str(atomicnumber).zfill(2) + '-' + atom_symbol + '.8.density.AE'
    elif kind == 'FC' and exchange == 'DEN':
        filename = str(atomicnumber).zfill(2) + '-' + atom_symbol + '.8.fc'
    elif kind == 'PAW' and exchange == 'GGA':
        filename = 'JTH-PBE-atomicdata-0.2/' + atom_symbol + '.GGA_PBE-JTH.xml'
    elif kind == 'PAW' and exchange == 'LDA':
        filename = 'JTH-LDA-atomicdata-0.2/' + atom_symbol + '.LDA_PW-JTH.xml'
    elif kind == 'HGH' and exchange == 'GGA':
        filename = str(atomicnumber).zfill(2) + atom_symbol.lower() + '.pbe_hgh'
    elif kind == 'ONC' and exchange == 'PBE':
        filename = 'pbe_s_sr' + os.sep + atom_symbol + '.psp8'
    else:
        print('The combination of exchange=%s and kind=%s is not known' % (exchange, kind))
        filename = ''
    return filename
コード例 #15
0
ファイル: OQMD2PyChemia.py プロジェクト: yfyh2013/PyChemia
def run_one(a):
    """
    Take one OQMD 'Entry' object, search all the calculations associated and take the best calculation
    in order to insert its data into the PyChemia Database

    :param a: OQMD Entry object
    :return:
    """

    energy = 1E10
    best_calculation = None

    if a.calculation_set.count() > 0:

        if 'standard' in a.calculations:
            best_calculation = a.calculations['standard']
            calculation_name = 'standard'
        elif 'fine_relax' in a.calculations:
            best_calculation = a.calculations['fine_relax']
            calculation_name = 'fine_relax'
        elif 'coarse_relax' in a.calculations:
            best_calculation = a.calculations['coarse_relax']
            calculation_name = 'coarse_relax'
        elif 'static' in a.calculations:
            best_calculation = a.calculations['static']
            calculation_name = 'static'
        elif 'relaxation' in a.calculations:
            best_calculation = a.calculations['relaxation']
            calculation_name = 'relaxation'
        elif len(a.calculations) > 0:
            calculations = sorted(a.calculations.keys())
            print('Calculations found: %s, using the last one' % calculations)
            best_calculation = a.calculations[calculations[-1]]
            calculation_name = calculations[-1]
        else:
            print('ERROR: Count > 0 and no calculation found')

    if best_calculation is not None:
        structure_name = None
        if best_calculation.output is not None:
            structure_used = best_calculation.output
            structure_id = best_calculation.output_id
            from_output = True
        elif best_calculation.input is not None:
            print(
                'WARNING: No data was found from the output of the calculation, using input geometries and leaving energetics empty'
            )
            structure_used = best_calculation.input
            structure_id = best_calculation.input_id
            from_output = False
    else:
        calculation_name = None
        if a.structures is not None and len(a.structures) > 0:
            struct_keys = sorted(a.structures.keys())
            print(
                "WARNING: Calculation not found for %s. Structures found: %s using the first one "
                % (a, struct_keys))
            structure_used = a.structures[struct_keys[0]]
            structure_id = None
            from_output = False
            structure_name = struct_keys[0]
        else:
            print("ERROR: No calculation and no structure found for %s" % a)
            return None, None

    cell = structure_used.cell.T
    symbols = atomic_symbol(structure_used.atomic_numbers)
    reduced = structure_used.coords

    structure = pychemia.Structure(cell=cell, symbols=symbols, reduced=reduced)
    entry_id = a.id

    if best_calculation is not None:
        calculation_id = best_calculation.id
        energy_pa = best_calculation.energy_pa
        energy = best_calculation.energy
        band_gap = best_calculation.band_gap
        settings = best_calculation.settings

        try:
            spacegroup_number = best_calculation.output.spacegroup.number
        except AttributeError:
            spacegroup_number = None

    else:
        calculation_id = None
        energy_pa = None
        energy = None
        band_gap = None
        settings = None
        spacegroup_number = None
        from_output = False

    try:
        symm = pychemia.crystal.CrystalSymmetry(structure)
        sym2 = symm.number(1E-2)
    except ValueError:
        sym2 = None

    properties = {
        'oqmd': {
            'structure_id': structure_id,
            'entry_id': entry_id,
            'calculation_id': calculation_id,
            'energy_pa': energy_pa,
            'energy': energy,
            'band_gap': band_gap,
            'settings': settings,
            'from_output': from_output,
            'calculation_name': calculation_name,
            'structure_name': structure_name,
            'spacegroup_number': spacegroup_number
        },
        'spacegroup_number': {
            'value': sym2,
            'symprec': 1E-2
        }
    }

    return structure, properties
コード例 #16
0
ファイル: input.py プロジェクト: kvlvn/PyChemia
    def get_structure(self, idtset=None, units='bohr'):
        """
        Return the atomic structure from the input object
        for a given dataset (no dataset by default)
        """
        # NATOM
        natom = self.get_value('natom', idtset)
        # SYMBOLS
        ntypat = self.get_value('ntypat', idtset)
        symbols = []
        znucl = self.get_value('znucl', idtset)
        typat = self.get_value('typat', idtset)
        for i in range(natom):
            # NOTE: znucl is a real number in OUT.nc
            # Alchemic mixing is not allow here
            if ntypat == 1:
                symbols.append(atomic_symbol(int(znucl)))
            else:
                symbols.append(atomic_symbol(int(znucl[typat[i] - 1])))

        # POSITIONS
        xangst = self.get_value('xangst', idtset)
        xcart = self.get_value('xcart', idtset)
        xred = self.get_value('xred', idtset)

        rprim = self.get_value('rprim', idtset)
        acell = np.array(self.get_value('acell', idtset))

        # Set rprimd and acell using the default values
        # if not found
        if rprim is None:
            rprim = np.identity(3)
        else:
            rprim = np.array(rprim).reshape((3, 3))
        if acell is None:
            acell = np.ones(3)

        rprimd = np.zeros((3, 3))
        rprimd[0] = rprim[0] * acell
        rprimd[1] = rprim[1] * acell
        rprimd[2] = rprim[2] * acell

        if xangst is not None:
            xangst = np.array(xangst)
            positions = xangst.reshape((natom, 3))
            if units == 'bohr':
                positions = positions * angstrom_bohr
        elif xcart is not None:
            xcart = np.array(xcart)
            positions = xcart.reshape((natom, 3))
            if units == 'angstrom':
                positions = positions * bohr_angstrom
        elif xred is not None:
            xred = np.array(xred)
            xred = xred.reshape((natom, 3))
            xcart = np.zeros((natom, 3))

            # print rprimd
            # print xred

            for i in range(natom):
                xcart[i] = xred[i, 0] * rprimd[0] + xred[i, 1] * rprimd[1] + xred[i, 2] * rprimd[2]

            positions = xcart
            if units == 'angstrom':
                positions = positions * bohr_angstrom

        else:
            positions = None

        if units == 'angstrom':
            rprimd = rprimd * bohr_angstrom

        # Create an object atomic_structure
        structure = Structure(natom=natom, symbols=symbols, positions=positions, cell=rprimd)

        return structure
コード例 #17
0
ファイル: input.py プロジェクト: MaterialsDiscovery/PyChemia
    def get_structure(self, idtset=None, units='bohr'):
        """
        Return the atomic structure from the input object
        for a given dataset (no dataset by default)
        """
        # NATOM
        natom = self.get_value('natom', idtset)
        # SYMBOLS
        ntypat = self.get_value('ntypat', idtset)
        symbols = []
        znucl = self.get_value('znucl', idtset)
        typat = self.get_value('typat', idtset)
        for i in range(natom):
            # NOTE: znucl is a real number in OUT.nc
            # Alchemic mixing is not allow here
            if ntypat == 1:
                symbols.append(atomic_symbol(int(znucl)))
            else:
                symbols.append(atomic_symbol(int(znucl[typat[i] - 1])))

        # POSITIONS
        xangst = self.get_value('xangst', idtset)
        xcart = self.get_value('xcart', idtset)
        xred = self.get_value('xred', idtset)

        rprim = self.get_value('rprim', idtset)
        acell = np.array(self.get_value('acell', idtset))

        # Set rprimd and acell using the default values
        # if not found
        if rprim is None:
            rprim = np.identity(3)
        else:
            rprim = np.array(rprim).reshape((3, 3))
        if acell is None:
            acell = np.ones(3)

        rprimd = np.zeros((3, 3))
        rprimd[0] = rprim[0] * acell
        rprimd[1] = rprim[1] * acell
        rprimd[2] = rprim[2] * acell

        if xangst is not None:
            xangst = np.array(xangst)
            positions = xangst.reshape((natom, 3))
            if units == 'bohr':
                positions = positions * angstrom_bohr
        elif xcart is not None:
            xcart = np.array(xcart)
            positions = xcart.reshape((natom, 3))
            if units == 'angstrom':
                positions = positions * bohr_angstrom
        elif xred is not None:
            xred = np.array(xred)
            xred = xred.reshape((natom, 3))
            xcart = np.zeros((natom, 3))

            # print rprimd
            # print xred

            for i in range(natom):
                xcart[i] = xred[i, 0] * rprimd[0] + xred[i, 1] * rprimd[1] + xred[i, 2] * rprimd[2]

            positions = xcart
            if units == 'angstrom':
                positions = positions * bohr_angstrom

        else:
            positions = None

        if units == 'angstrom':
            rprimd = rprimd * bohr_angstrom

        # Create an object atomic_structure
        structure = Structure(natom=natom, symbols=symbols, positions=positions, cell=rprimd)

        return structure
コード例 #18
0
def run_one(a):
    """
    Take one OQMD 'Entry' object, search all the calculations associated and take the best calculation
    in order to insert its data into the PyChemia Database

    :param a: OQMD Entry object
    :return:
    """

    energy = 1E10
    best_calculation = None

    if a.calculation_set.count() > 0:

        if 'standard' in a.calculations:
            best_calculation = a.calculations['standard']
            calculation_name = 'standard'
        elif 'fine_relax' in a.calculations:
            best_calculation = a.calculations['fine_relax']
            calculation_name = 'fine_relax'
        elif 'coarse_relax' in a.calculations:
            best_calculation = a.calculations['coarse_relax']
            calculation_name = 'coarse_relax'
        elif 'static' in a.calculations:
            best_calculation = a.calculations['static']
            calculation_name = 'static'
        elif 'relaxation' in a.calculations:
            best_calculation = a.calculations['relaxation']
            calculation_name = 'relaxation'
        elif len(a.calculations) > 0:
            calculations = sorted(a.calculations.keys())
            print('Calculations found: %s, using the last one' % calculations)
            best_calculation = a.calculations[calculations[-1]]
            calculation_name = calculations[-1]
        else:
            print('ERROR: Count > 0 and no calculation found')

    if best_calculation is not None:
        structure_name = None
        if best_calculation.output is not None:
            structure_used = best_calculation.output
            structure_id = best_calculation.output_id
            from_output = True
        elif best_calculation.input is not None:
            print(
                'WARNING: No data was found from the output of the calculation, using input geometries and leaving '
                'energetics empty')
            structure_used = best_calculation.input
            structure_id = best_calculation.input_id
            from_output = False
    else:
        calculation_name = None
        if a.structures is not None and len(a.structures) > 0:
            struct_keys = sorted(a.structures.keys())
            print("WARNING: Calculation not found for %s. Structures found: %s using the first one " % (a, struct_keys))
            structure_used = a.structures[struct_keys[0]]
            structure_id = None
            from_output = False
            structure_name = struct_keys[0]
        else:
            print("ERROR: No calculation and no structure found for %s" % a)
            return None, None

    cell = structure_used.cell.T
    symbols = atomic_symbol(structure_used.atomic_numbers)
    reduced = structure_used.coords

    structure = pychemia.Structure(cell=cell, symbols=symbols, reduced=reduced)
    entry_id = a.id

    if best_calculation is not None:
        calculation_id = best_calculation.id
        energy_pa = best_calculation.energy_pa
        energy = best_calculation.energy
        band_gap = best_calculation.band_gap
        settings = best_calculation.settings

        try:
            spacegroup_number = best_calculation.output.spacegroup.number
        except AttributeError:
            spacegroup_number = None

    else:
        calculation_id = None
        energy_pa = None
        energy = None
        band_gap = None
        settings = None
        spacegroup_number = None
        from_output = False

    try:
        symm = pychemia.crystal.CrystalSymmetry(structure)
        sym2 = symm.number(1E-2)
    except ValueError:
        sym2 = None

    properties = {'oqmd': {'structure_id': structure_id,
                           'entry_id': entry_id,
                           'calculation_id': calculation_id,
                           'energy_pa': energy_pa,
                           'energy': energy,
                           'band_gap': band_gap,
                           'settings': settings,
                           'from_output': from_output,
                           'calculation_name': calculation_name,
                           'structure_name': structure_name,
                           'spacegroup_number': spacegroup_number},
                  'spacegroup_number': {'value': sym2, 'symprec': 1E-2}}

    return structure, properties