Statistiques
| Révision :

root / ase / io / __init__.py

Historique | Voir | Annoter | Télécharger (13,86 ko)

1
import os
2
import sys
3
from os.path import basename
4
from tarfile import is_tarfile
5
from zipfile import is_zipfile
6

    
7
from ase.atoms import Atoms
8
from ase.units import Bohr
9
from ase.io.trajectory import PickleTrajectory
10

    
11
__all__ = ['read', 'write', 'PickleTrajectory']
12

    
13

    
14
def read(filename, index=-1, format=None):
15
    """Read Atoms object(s) from file.
16

17
    filename: str
18
        Name of the file to read from.
19
    index: int or slice
20
        If the file contains several configurations, the last configuration
21
        will be returned by default.  Use index=n to get configuration
22
        number n (counting from zero).
23
    format: str
24
        Used to specify the file-format.  If not given, the
25
        file-format will be guessed by the *filetype* function.
26

27
    Known formats:
28

29
    =========================  ===========
30
    format                     short name
31
    =========================  ===========
32
    GPAW restart-file          gpw
33
    Dacapo netCDF output file  dacapo
34
    Old ASE netCDF trajectory  nc
35
    Virtual Nano Lab file      vnl
36
    ASE pickle trajectory      traj
37
    GPAW text output           gpaw-text
38
    CUBE file                  cube
39
    XCrySDen Structure File    xsf  
40
    Dacapo text output         dacapo-text
41
    XYZ-file                   xyz
42
    VASP POSCAR/CONTCAR file   vasp
43
    VASP OUTCAR file           vasp_out
44
    Protein Data Bank          pdb
45
    FHI-aims geometry file     aims
46
    FHI-aims output file       aims_out
47
    VTK XML Image Data         vti
48
    VTK XML Structured Grid    vts
49
    VTK XML Unstructured Grid  vtu
50
    TURBOMOLE coord file       tmol
51
    exciting input             exi
52
    AtomEye configuration      cfg
53
    WIEN2k structure file      struct
54
    DftbPlus input file        dftb
55
    =========================  ===========
56

57
    """
58
    if isinstance(filename, str):
59
        p = filename.rfind('@')
60
        if p != -1:
61
            try:
62
                index = string2index(filename[p + 1:])
63
            except ValueError:
64
                pass
65
            else:
66
                filename = filename[:p]
67

    
68
    if isinstance(index, str):
69
        index = string2index(index)
70

    
71
    if format is None:
72
        format = filetype(filename)
73

    
74
    if format.startswith('gpw'):
75
        import gpaw
76
        r = gpaw.io.open(filename, 'r')
77
        positions = r.get('CartesianPositions') * Bohr
78
        numbers = r.get('AtomicNumbers')
79
        cell = r.get('UnitCell') * Bohr
80
        pbc = r.get('BoundaryConditions')
81
        tags = r.get('Tags')
82
        magmoms = r.get('MagneticMoments')
83

    
84
        atoms = Atoms(positions=positions,
85
                      numbers=numbers,
86
                      cell=cell,
87
                      pbc=pbc)
88
        if tags.any():
89
            atoms.set_tags(tags)
90
        if magmoms.any():
91
            atoms.set_initial_magnetic_moments(magmoms)
92

    
93
        return atoms
94

    
95
    if format == 'exi':
96
        from ase.io.exciting import read_exciting
97
        return read_exciting(filename, index)
98

    
99
    if format == 'xyz':
100
        from ase.io.xyz import read_xyz
101
        return read_xyz(filename, index)
102

    
103
    if format == 'traj':
104
        from ase.io.trajectory import read_trajectory
105
        return read_trajectory(filename, index)
106

    
107
    if format == 'cube':
108
        from ase.io.cube import read_cube
109
        return read_cube(filename, index)
110

    
111
    if format == 'nc':
112
        from ase.io.netcdf import read_netcdf
113
        return read_netcdf(filename, index)
114

    
115
    if format == 'gpaw-text':
116
        from ase.io.gpawtext import read_gpaw_text
117
        return read_gpaw_text(filename, index)
118

    
119
    if format == 'dacapo-text':
120
        from ase.io.dacapo import read_dacapo_text
121
        return read_dacapo_text(filename)
122

    
123
    if format == 'dacapo':
124
        from ase.io.dacapo import read_dacapo
125
        return read_dacapo(filename)
126
    
127
    if format == 'xsf':
128
        from ase.io.xsf import read_xsf
129
        return read_xsf(filename, index)
130

    
131
    if format == 'vasp':
132
        from ase.io.vasp import read_vasp
133
        return read_vasp(filename)
134
    
135
    if format == 'vasp_out':
136
        from ase.io.vasp import read_vasp_out
137
        return read_vasp_out(filename, index)
138
    
139
    if format == 'mol':
140
        from ase.io.mol import read_mol
141
        return read_mol(filename)
142

    
143
    if format == 'pdb':
144
        from ase.io.pdb import read_pdb
145
        return read_pdb(filename)
146

    
147
    if format == 'cif':
148
        from ase.io.cif import read_cif
149
        return read_cif(filename)
150

    
151
    if format == 'struct':
152
        from ase.io.wien2k import read_struct
153
        return read_struct(filename)
154

    
155
    if format == 'vti':
156
        from ase.io.vtkxml import read_vti
157
        return read_vti(filename)
158

    
159
    if format == 'vts':
160
        from ase.io.vtkxml import read_vts
161
        return read_vts(filename)
162

    
163
    if format == 'vtu':
164
        from ase.io.vtkxml import read_vtu
165
        return read_vtu(filename)
166

    
167
    if format == 'aims':
168
        from ase.io.aims import read_aims
169
        return read_aims(filename)
170
    
171
    if format == 'aims_out':
172
        from ase.io.aims import read_aims_output
173
        return read_aims_output(filename, index)
174

    
175
    if format == 'iwm':
176
        from ase.io.iwm import read_iwm
177
        return read_iwm(filename)
178

    
179
    if format == 'Cmdft':
180
        from ase.io.cmdft import read_I_info
181
        return read_I_info(filename)
182

    
183
    if format == 'tmol':
184
        from ase.io.turbomole import read_turbomole
185
        return read_turbomole(filename)
186

    
187
    if format == 'cfg':
188
        from ase.io.cfg import read_cfg
189
        return read_cfg(filename)
190

    
191
    if format == 'dftb':
192
        from ase.io.dftb import read_dftb
193
        return read_dftb(filename)
194

    
195
    if format == 'sdf':
196
        from ase.io.sdf import read_sdf
197
        return read_sdf(filename)
198

    
199
    raise RuntimeError('File format descriptor '+format+' not recognized!')
200

    
201

    
202
def write(filename, images, format=None, **kwargs):
203
    """Write Atoms object(s) to file.
204

205
    filename: str
206
        Name of the file to write to.
207
    images: Atoms object or list of Atoms objects
208
        A single Atoms object or a list of Atoms objects.
209
    format: str
210
        Used to specify the file-format.  If not given, the
211
        file-format will be taken from suffix of the filename. 
212

213
    The accepted output formats:
214
  
215
    =========================  ===========
216
    format                     short name
217
    =========================  ===========
218
    ASE pickle trajectory      traj
219
    CUBE file                  cube
220
    XYZ-file                   xyz
221
    VASP POSCAR/CONTCAR file   vasp
222
    Protein Data Bank          pdb
223
    XCrySDen Structure File    xsf
224
    FHI-aims geometry file     aims
225
    gOpenMol .plt file         plt  
226
    Python script              py
227
    Encapsulated Postscript    eps
228
    Portable Network Graphics  png
229
    Persistance of Vision      pov
230
    VTK XML Image Data         vti
231
    VTK XML Structured Grid    vts
232
    VTK XML Unstructured Grid  vtu
233
    TURBOMOLE coord file       tmol
234
    exciting                   exi
235
    AtomEye configuration      cfg
236
    WIEN2k structure file      struct
237
    DftbPlus input file        dftb
238
    =========================  ===========
239
  
240
    The use of additional keywords is format specific.
241
  
242
    The ``cube`` and ``plt`` formats accept (plt requires it) a ``data``
243
    keyword, which can be used to write a 3D array to the file along
244
    with the nuclei coordinates.
245
  
246
    The ``vti``, ``vts`` and ``vtu`` formats are all specifically directed
247
    for use with MayaVi, and the latter is designated for visualization of
248
    the atoms whereas the two others are intended for volume data. Further,
249
    it should be noted that the ``vti`` format is intended for orthogonal
250
    unit cells as only the grid-spacing is stored, whereas the ``vts`` format
251
    additionally stores the coordinates of each grid point, thus making it
252
    useful for volume date in more general unit cells.
253

254
    The ``eps``, ``png``, and ``pov`` formats are all graphics formats,
255
    and accept the additional keywords:
256

257
    rotation: str (default '')
258
      The rotation angles, e.g. '45x,70y,90z'.
259

260
    show_unit_cell: int (default 0)
261
      Can be 0, 1, 2 to either not show, show, or show all of the unit cell.
262

263
    radii: array or float (default 1.0)
264
      An array of same length as the list of atoms indicating the sphere radii.
265
      A single float specifies a uniform scaling of the default covalent radii.
266

267
    bbox: 4 floats (default None)
268
      Set the bounding box to (xll, yll, xur, yur) (lower left, upper right).
269

270
    colors: array (default None)
271
      An array of same length as the list of atoms, indicating the rgb color
272
      code for each atom. Default is the jmol_colors of ase/data/colors.
273

274
    scale: int (default 20)
275
      Number of pixels per Angstrom.
276
      
277
    For the ``pov`` graphics format, ``scale`` should not be specified.
278
    The elements of the color array can additionally be strings, or 4
279
    and 5 vectors for named colors, rgb + filter, and rgb + filter + transmit
280
    specification. This format accepts the additional keywords:
281

282
    ``run_povray``, ``display``, ``pause``, ``transparent``,
283
    ``canvas_width``, ``canvas_height``, ``camera_dist``,
284
    ``image_plane``, ``camera_type``, ``point_lights``,
285
    ``area_light``, ``background``, ``textures``, ``celllinewidth``,
286
    ``bondlinewidth``, ``bondatoms``
287
    """
288
    
289
    if format is None:
290
        if filename == '-':
291
            format = 'xyz'
292
            filename = sys.stdout
293
        elif 'POSCAR' in filename or 'CONTCAR' in filename:
294
            format = 'vasp'
295
        elif 'OUTCAR' in filename:
296
            format = 'vasp_out'
297
        else:
298
            suffix = filename.split('.')[-1]
299
            format = {}.get(suffix, suffix) # XXX this does not make sense
300
            # Maybe like this:
301
##             format = {'traj': 'trajectory',
302
##                       'nc': 'netcdf',
303
##                       'exi': 'exciting',
304
##                       'in': 'aims',
305
##                       'tmol': 'turbomole',
306
##                       }.get(suffix, suffix)
307

    
308
    if format == 'exi':
309
        from ase.io.exciting import write_exciting
310
        write_exciting(filename, images)
311
        return
312

    
313

    
314
    if format == 'xyz':
315
        from ase.io.xyz import write_xyz
316
        write_xyz(filename, images)
317
        return
318
    elif format == 'in':
319
        format = 'aims'
320
    elif format == 'tmol':
321
        from ase.io.turbomole import write_turbomole
322
        write_turbomole(filename, images)
323
        return
324
    elif format == 'dftb':
325
        from ase.io.dftb import write_dftb
326
        write_dftb(filename, images)
327
        return
328
    elif format == 'struct':
329
        from ase.io.wien2k import write_struct
330
        write_struct(filename, images, **kwargs)
331
        return
332

    
333
    format = {'traj': 'trajectory', 'nc': 'netcdf'}.get(format, format)
334
    name = 'write_' + format
335

    
336
    if format in ['vti', 'vts', 'vtu']:
337
        format = 'vtkxml'
338

    
339
    if format is None:
340
        format = filetype(filename)
341

    
342
    try:
343
        write = getattr(__import__('ase.io.%s' % format, {}, {}, [name]), name)
344
    except ImportError:
345
        raise TypeError('Unknown format: "%s".' % format)
346
    
347
    write(filename, images, **kwargs)
348

    
349

    
350
def string2index(string):
351
    if ':' not in string:
352
        return int(string)
353
    i = []
354
    for s in string.split(':'):
355
        if s == '':
356
            i.append(None)
357
        else:
358
            i.append(int(s))
359
    i += (3 - len(i)) * [None]
360
    return slice(*i)
361

    
362

    
363
def filetype(filename):
364
    """Try to guess the type of the file."""
365
    fileobj = open(filename)
366
    s3 = fileobj.read(3)
367
    if len(s3) == 0:
368
        raise IOError('Empty file: ' + filename)
369
    
370
    if is_tarfile(filename):
371
        return 'gpw'
372

    
373
    if s3 == 'CDF':
374
        from ase.io.pupynere import NetCDFFile
375
        nc = NetCDFFile(filename)
376
        if 'number_of_dynamic_atoms' in nc.dimensions:
377
            return 'dacapo'
378

    
379
        history = nc.history
380
        if history == 'GPAW restart file':
381
            return 'gpw-nc'
382
        if history == 'ASE trajectory':
383
            return 'nc'
384
        if history == 'Dacapo':
385
            return 'dacapo'
386
        raise IOError('Unknown netCDF file!')
387

    
388
    
389
    if is_zipfile(filename):
390
        return 'vnl'
391

    
392
    fileobj.seek(0)
393
    lines = fileobj.readlines(1000)
394

    
395
    if lines[0].startswith('PickleTrajectory'):
396
        return 'traj'
397

    
398
    if lines[1].startswith('OUTER LOOP:') or filename.lower().endswith('.cube'):
399
        return 'cube'
400
    
401
    if '  ___ ___ ___ _ _ _  \n' in lines:
402
        return 'gpaw-text'
403

    
404
    if (' &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\n'
405
        in lines[:90]):
406
        return 'dacapo-text'
407

    
408
    for word in ['ANIMSTEPS', 'CRYSTAL', 'SLAB', 'POLYMER', 'MOLECULE']:
409
        if lines[0].startswith(word):
410
            return 'xsf'
411

    
412
    filename_v = basename(filename) 
413
    if 'POSCAR' in filename_v or 'CONTCAR' in filename_v:
414
        return 'vasp'    
415

    
416
    if 'OUTCAR' in filename_v:
417
        return 'vasp_out'
418
    
419
    if filename.lower().endswith('.exi'):
420
        return 'exi'
421
    
422
    if filename.lower().endswith('.mol'):
423
        return 'mol'
424

    
425
    if filename.lower().endswith('.pdb'):
426
        return 'pdb'
427

    
428
    if filename.lower().endswith('.cif'):
429
        return 'cif'
430
   
431
    if filename.lower().endswith('.struct'):
432
        return 'struct'
433

    
434
    if filename.lower().endswith('.in'):
435
        return 'aims'
436

    
437
    if filename.lower().endswith('.out'):
438
        return 'aims_out'
439

    
440
    if filename.lower().endswith('.cfg'):
441
        return 'cfg'
442
        
443
    if os.path.split(filename)[1] == 'atoms.dat':
444
        return 'iwm'
445

    
446
    if filename.endswith('I_info'):
447
        return 'Cmdft'
448

    
449
    if lines[0].startswith('$coord'):
450
        return 'tmol'
451

    
452
    if lines[0].startswith('Geometry'):
453
        return 'dftb'
454

    
455
    if s3 == '<?x':
456
        from ase.io.vtkxml import probe_vtkxml
457
        xmltype = probe_vtkxml(filename)
458
        if xmltype == 'ImageData':
459
            return 'vti'
460
        elif xmltype == 'StructuredGrid':
461
            return 'vts'
462
        elif xmltype == 'UnstructuredGrid':
463
            return 'vtu'
464
        elif xmltype is not None:
465
            raise IOError('Unknown VTK XML file!')
466

    
467
    if filename.lower().endswith('.sdf'):
468
        return 'sdf'
469

    
470
    return 'xyz'