Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 130 additions & 10 deletions xyz2povray.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,138 @@
class Atom:
"""define appearance of atoms as colored spheres"""

# define the properties for different species
# RGB values of the Jmol scheme
# reference: https://jmol.sourceforge.net/jscolors/
properties = {
'H': {'mass': 1, 'rad': 0.25, 'rgb': [1.00, 1.00, 1.00]},
'He': {'mass': 4, 'rad': 0.25, 'rgb': [0.85, 1.00, 1.00]},
'Li': {'mass': 6, 'rad': 0.25, 'rgb': [0.80, 0.51, 1.00]},
'Be': {'mass': 9, 'rad': 0.25, 'rgb': [0.76, 1.00, 0.00]},
'B': {'mass': 11, 'rad': 0.25, 'rgb': [1.00, 0.71, 0.71]},
'C': {'mass': 12, 'rad': 0.25, 'rgb': [0.56, 0.56, 0.56]},
'N': {'mass': 14, 'rad': 0.25, 'rgb': [0.19, 0.31, 0.97]},
'O': {'mass': 16, 'rad': 0.25, 'rgb': [1.00, 0.05, 0.05]},
'F': {'mass': 19, 'rad': 0.25, 'rgb': [0.56, 0.88, 0.31]},
'Ne': {'mass': 20, 'rad': 0.25, 'rgb': [0.70, 0.89, 0.96]},
'Na': {'mass': 22, 'rad': 0.25, 'rgb': [0.67, 0.36, 0.95]},
'Mg': {'mass': 24, 'rad': 0.25, 'rgb': [0.54, 1.00, 0.00]},
'Al': {'mass': 27, 'rad': 0.25, 'rgb': [0.75, 0.65, 0.65]},
'Si': {'mass': 29, 'rad': 0.25, 'rgb': [0.94, 0.78, 0.63]},
'P': {'mass': 31, 'rad': 0.25, 'rgb': [1.00, 0.50, 0.00]},
'S': {'mass': 32, 'rad': 0.25, 'rgb': [1.00, 1.00, 0.19]},
'Cl': {'mass': 35, 'rad': 0.25, 'rgb': [0.12, 0.94, 0.12]},
'Ar': {'mass': 40, 'rad': 0.25, 'rgb': [0.50, 0.82, 0.89]},
'K': {'mass': 39, 'rad': 0.25, 'rgb': [0.56, 0.25, 0.83]},
'Ca': {'mass': 40, 'rad': 0.25, 'rgb': [0.24, 1.00, 0.00]},
'Sc': {'mass': 45, 'rad': 0.25, 'rgb': [0.90, 0.90, 0.90]},
'Ti': {'mass': 48, 'rad': 0.25, 'rgb': [0.75, 0.76, 0.78]},
'V': {'mass': 51, 'rad': 0.25, 'rgb': [0.65, 0.65, 0.78]},
'Cr': {'mass': 52, 'rad': 0.25, 'rgb': [0.54, 0.60, 0.78]},
'Mn': {'mass': 55, 'rad': 0.25, 'rgb': [0.61, 0.48, 0.78]},
'Fe': {'mass': 56, 'rad': 0.25, 'rgb': [0.88, 0.40, 0.20]},
'Co': {'mass': 59, 'rad': 0.25, 'rgb': [0.94, 0.56, 0.62]},
'Ni': {'mass': 59, 'rad': 0.25, 'rgb': [0.31, 0.82, 0.31]},
'Cu': {'mass': 63, 'rad': 0.25, 'rgb': [0.78, 0.50, 0.20]},
'Zn': {'mass': 65, 'rad': 0.25, 'rgb': [0.49, 0.50, 0.69]},
'Ga': {'mass': 70, 'rad': 0.25, 'rgb': [0.76, 0.56, 0.56]},
'Ge': {'mass': 73, 'rad': 0.25, 'rgb': [0.40, 0.56, 0.56]},
'As': {'mass': 75, 'rad': 0.25, 'rgb': [0.74, 0.50, 0.89]},
'Se': {'mass': 79, 'rad': 0.25, 'rgb': [1.00, 0.63, 0.00]},
'Br': {'mass': 80, 'rad': 0.25, 'rgb': [0.65, 0.16, 0.16]},
'Kr': {'mass': 84, 'rad': 0.25, 'rgb': [0.36, 0.72, 0.82]},
'Rb': {'mass': 86, 'rad': 0.25, 'rgb': [0.43, 0.18, 0.69]},
'Sr': {'mass': 88, 'rad': 0.25, 'rgb': [0.00, 1.00, 0.00]},
'Y': {'mass': 89, 'rad': 0.25, 'rgb': [0.58, 1.00, 1.00]},
'Zr': {'mass': 91, 'rad': 0.25, 'rgb': [0.58, 0.88, 0.88]},
'Nb': {'mass': 93, 'rad': 0.25, 'rgb': [0.45, 0.76, 0.79]},
'Mo': {'mass': 96, 'rad': 0.25, 'rgb': [0.32, 0.71, 0.71]},
'Tc': {'mass': 97, 'rad': 0.25, 'rgb': [0.23, 0.62, 0.62]},
'Ru': {'mass': 101, 'rad': 0.25, 'rgb': [0.14, 0.56, 0.56]},
'Rh': {'mass': 103, 'rad': 0.25, 'rgb': [0.04, 0.49, 0.55]},
'Pd': {'mass': 106, 'rad': 0.25, 'rgb': [0.00, 0.41, 0.52]},
'Ag': {'mass': 108, 'rad': 0.25, 'rgb': [0.75, 0.75, 0.75]},
'Cd': {'mass': 112, 'rad': 0.25, 'rgb': [1.00, 0.85, 0.56]},
'In': {'mass': 115, 'rad': 0.25, 'rgb': [0.65, 0.46, 0.45]},
'Sn': {'mass': 117, 'rad': 0.25, 'rgb': [0.40, 0.50, 0.50]},
'Sb': {'mass': 122, 'rad': 0.25, 'rgb': [0.62, 0.39, 0.71]},
'Te': {'mass': 128, 'rad': 0.25, 'rgb': [0.83, 0.48, 0.00]},
'I': {'mass': 127, 'rad': 0.25, 'rgb': [0.58, 0.00, 0.58]},
'Xe': {'mass': 131, 'rad': 0.25, 'rgb': [0.26, 0.62, 0.69]},
'Cs': {'mass': 133, 'rad': 0.25, 'rgb': [0.34, 0.09, 0.56]},
'Ba': {'mass': 137, 'rad': 0.25, 'rgb': [0.00, 0.79, 0.00]},
'La': {'mass': 139, 'rad': 0.25, 'rgb': [0.44, 0.83, 1.00]},
'Ce': {'mass': 140, 'rad': 0.25, 'rgb': [1.00, 1.00, 0.78]},
'Pr': {'mass': 141, 'rad': 0.25, 'rgb': [0.85, 1.00, 0.78]},
'Nd': {'mass': 144, 'rad': 0.25, 'rgb': [0.78, 1.00, 0.78]},
'Pm': {'mass': 145, 'rad': 0.25, 'rgb': [0.64, 1.00, 0.78]},
'Sm': {'mass': 150, 'rad': 0.25, 'rgb': [0.56, 1.00, 0.78]},
'Eu': {'mass': 152, 'rad': 0.25, 'rgb': [0.38, 1.00, 0.78]},
'Gd': {'mass': 157, 'rad': 0.25, 'rgb': [0.27, 1.00, 0.78]},
'Tb': {'mass': 159, 'rad': 0.25, 'rgb': [0.19, 1.00, 0.78]},
'Dy': {'mass': 163, 'rad': 0.25, 'rgb': [0.12, 1.00, 0.78]},
'Ho': {'mass': 165, 'rad': 0.25, 'rgb': [0.00, 1.00, 0.61]},
'Er': {'mass': 167, 'rad': 0.25, 'rgb': [0.00, 0.90, 0.46]},
'Tm': {'mass': 169, 'rad': 0.25, 'rgb': [0.00, 0.83, 0.32]},
'Yb': {'mass': 173, 'rad': 0.25, 'rgb': [0.00, 0.75, 0.22]},
'Lu': {'mass': 175, 'rad': 0.25, 'rgb': [0.00, 0.67, 0.14]},
'Hf': {'mass': 179, 'rad': 0.25, 'rgb': [0.30, 0.76, 1.00]},
'Ta': {'mass': 181, 'rad': 0.25, 'rgb': [0.30, 0.65, 1.00]},
'W': {'mass': 184, 'rad': 0.25, 'rgb': [0.13, 0.58, 0.84]},
'Re': {'mass': 186, 'rad': 0.25, 'rgb': [0.15, 0.49, 0.67]},
'Os': {'mass': 190, 'rad': 0.25, 'rgb': [0.15, 0.40, 0.59]},
'Ir': {'mass': 192, 'rad': 0.25, 'rgb': [0.09, 0.33, 0.53]},
'Pt': {'mass': 195, 'rad': 0.25, 'rgb': [0.82, 0.82, 0.88]},
'Au': {'mass': 197, 'rad': 0.25, 'rgb': [1.00, 0.82, 0.14]},
'Hg': {'mass': 201, 'rad': 0.25, 'rgb': [0.72, 0.72, 0.82]},
'Tl': {'mass': 204, 'rad': 0.25, 'rgb': [0.65, 0.33, 0.30]},
'Pb': {'mass': 207, 'rad': 0.25, 'rgb': [0.34, 0.35, 0.38]},
'Bi': {'mass': 209, 'rad': 0.25, 'rgb': [0.62, 0.31, 0.71]},
'Po': {'mass': 209, 'rad': 0.25, 'rgb': [0.67, 0.36, 0.00]},
'At': {'mass': 210, 'rad': 0.25, 'rgb': [0.46, 0.31, 0.27]},
'Rn': {'mass': 222, 'rad': 0.25, 'rgb': [0.26, 0.51, 0.59]},
'Fr': {'mass': 223, 'rad': 0.25, 'rgb': [0.26, 0.00, 0.40]},
'Ra': {'mass': 226, 'rad': 0.25, 'rgb': [0.00, 0.49, 0.00]},
'Ac': {'mass': 227, 'rad': 0.25, 'rgb': [0.44, 0.67, 1.00]},
'Th': {'mass': 232, 'rad': 0.25, 'rgb': [0.00, 0.73, 1.00]},
'Pa': {'mass': 231, 'rad': 0.25, 'rgb': [0.00, 0.63, 1.00]},
'U': {'mass': 238, 'rad': 0.25, 'rgb': [0.00, 0.56, 1.00]},
'Np': {'mass': 237, 'rad': 0.25, 'rgb': [0.00, 0.50, 1.00]},
'Pu': {'mass': 244, 'rad': 0.25, 'rgb': [0.00, 0.42, 1.00]},
'Am': {'mass': 243, 'rad': 0.25, 'rgb': [0.33, 0.36, 0.95]},
'Cm': {'mass': 247, 'rad': 0.25, 'rgb': [0.47, 0.36, 0.89]},
'Bk': {'mass': 247, 'rad': 0.25, 'rgb': [0.54, 0.31, 0.89]},
'Cf': {'mass': 251, 'rad': 0.25, 'rgb': [0.63, 0.21, 0.83]},
'Es': {'mass': 252, 'rad': 0.25, 'rgb': [0.70, 0.12, 0.83]},
'Fm': {'mass': 257, 'rad': 0.25, 'rgb': [0.70, 0.12, 0.73]},
'Md': {'mass': 258, 'rad': 0.25, 'rgb': [0.70, 0.05, 0.65]},
'No': {'mass': 259, 'rad': 0.25, 'rgb': [0.74, 0.05, 0.53]},
'Lr': {'mass': 260, 'rad': 0.25, 'rgb': [0.78, 0.00, 0.40]},
'Rf': {'mass': 261, 'rad': 0.25, 'rgb': [0.80, 0.00, 0.35]},
'Db': {'mass': 262, 'rad': 0.25, 'rgb': [0.82, 0.00, 0.31]},
'Sg': {'mass': 269, 'rad': 0.25, 'rgb': [0.85, 0.00, 0.27]},
'Bh': {'mass': 270, 'rad': 0.25, 'rgb': [0.88, 0.00, 0.22]},
'Hs': {'mass': 269, 'rad': 0.25, 'rgb': [0.90, 0.00, 0.18]},
'Mt': {'mass': 278, 'rad': 0.25, 'rgb': [0.92, 0.00, 0.15]},
}

def __init__(self, species, tag, position=[0, 0, 0]):
self.species = species
self.tag = tag
self.position = np.array(position)

if self.species == 'C':
self.mass = 12
self.rad = 0.25
self.rgb = [0.4, 0.4, 0.4]
else:
# set the properties based on the species
if self.species in Atom.properties:
prop = Atom.properties[self.species]
self.mass = prop['mass']
self.rad = prop['rad']
self.rgb = prop['rgb']
else: # default to hydrogen
self.mass = 1
self.rad = 0.25
self.rgb = [0.75, 0.75, 0.75]
print(f"WARNING: structure contains {self.species}, an atom unknown to the program.")


def __repr__(self):
return "%r %r tag: %r pos: %r, %r, %r" % (
Expand Down Expand Up @@ -64,6 +183,7 @@ def toPOV(self):


def get_structure(data):
"""access atomic coordinates"""
atoms = np.array([])
with open(data) as xyz:
for ii, line in enumerate(xyz):
Expand All @@ -78,25 +198,25 @@ def get_structure(data):
return atoms


def get_center_of_mass(Molecule):
def get_center_of_mass(molecule):
"""determine the molecule's center of gravity

Note: this is literally by the atoms' masses, and not only by mere dimension
of the molecule in 3D."""
center_of_mass = np.array([0.0, 0.0, 0.0])
total_mass = 0.0

for atom in Molecule:
for atom in molecule:
center_of_mass += atom.mass * atom.position
total_mass += atom.mass
center_of_mass /= total_mass

return np.around(center_of_mass, decimals=2)


def move2origin(Molecule, center_of_mass):
def move2origin(molecule, center_of_mass):
"""align molecule's centre of gravity and origin of the coordinate system"""
for atom in Molecule:
for atom in molecule:
atom.translate(center_of_mass)


Expand Down Expand Up @@ -186,7 +306,7 @@ def get_args():
global_settings {ambient_light rgb <0.200, 0.200, 0.200>
max_trace_level 15}

background {color rgb <1,1,1>}
background {color rgb <0.8,0.8,0.8>}

camera {
orthographic
Expand Down