source: trunk/exports/G2export_PDB.py

Last change on this file was 5576, checked in by toby, 2 years ago

rework docs for exports

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 12.5 KB
RevLine 
[1299]1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3########### SVN repository information ###################
4# $Date: 2023-05-11 19:22:54 +0000 (Thu, 11 May 2023) $
5# $Author: toby $
6# $Revision: 5576 $
7# $URL: trunk/exports/G2export_PDB.py $
8# $Id: G2export_PDB.py 5576 2023-05-11 19:22:54Z toby $
9########### SVN repository information ###################
[5576]10'''Classes in :mod:`G2export_PDB` follow:
[1299]11'''
[3136]12from __future__ import division, print_function
[1299]13import numpy as np
14import os.path
15import GSASIIpath
16GSASIIpath.SetVersionNumber("$Revision: 5576 $")
17import GSASIIIO as G2IO
18import GSASIIlattice as G2lat
19
20class ExportPhasePDB(G2IO.ExportBaseclass):
21    '''Used to create a PDB file for a phase
22
23    :param wx.Frame G2frame: reference to main GSAS-II frame
24    '''
25    def __init__(self,G2frame):
26        super(self.__class__,self).__init__( # fancy way to say <parentclass>.__init__
27            G2frame=G2frame,
28            formatName = 'PDB',
29            extension='.PDB',
30            longFormatName = 'Export phase as .PDB file'
31            )
32        self.exporttype = ['phase']
33        self.multiple = True
34
35    def Exporter(self,event=None):
36        '''Export as a PDB file
37        '''
38       
39        def PDBheader():
40            self.Write("HEADER phase "+str(phasenam)+" from "+str(self.G2frame.GSASprojectfile))
41            self.Write("TITLE")
42            self.Write("COMPND")
43            self.Write("SOURCE")
44            self.Write("KEYWDS")
45            self.Write("EXPDTA    X-RAY POWDER DIFFRACTION")
46            self.Write("REVDAT")
47            self.Write("JRNL")
48            self.Write("REMARK   1")
49            self.Write("REMARK   2")                                                                     
50            self.Write("REMARK   2 RESOLUTION. 2.66 ANGSTROMS.")                                         
51            self.Write("REMARK   2 POWDER DIFFRACTION MINIMUM D-SPACING.")
52           
53        def PDBremark250():                               
54            self.Write('REMARK 250')                                                                     
55            self.Write('REMARK 250 REFINEMENT.')                                                         
56            self.Write('REMARK 250   PROGRAM     : GSAS-II')                                                 
57            self.Write('REMARK 250   AUTHORS     : TOBY & VON DREELE')
58            self.Write('REMARK 250   REFRENCE    : J. APPL. CRYST. 46, 544-549(2013)')                             
59            self.Write('REMARK 250')
60            self.Write('REMARK 250  DATA USED IN REFINEMENT')                                             
61            self.Write('REMARK 250   RESOLUTION RANGE HIGH (ANGSTROMS) :  x.xx')                         
62            self.Write('REMARK 250   RESOLUTION RANGE LOW  (ANGSTROMS) : xx.xx')                         
63            self.Write('REMARK 250   POWDER DIFFRACTION DATA.')                                           
64            self.Write('REMARK 250')
65            self.Write('REMARK 250  FIT TO DATA USED IN REFINEMENT')                                     
66            self.Write('REMARK 250   NUMBER OF POWDER PATTERNS         :     x')                         
67            self.Write('REMARK 250   PROFILE R VALUES              (%) :  x.xx')                         
68            self.Write('REMARK 250   WEIGHTED PROFILE R VALUES     (%) :  x.xx')                         
69            self.Write('REMARK 250   F**2 R VALUES                 (%) : xx.xx')                         
70            self.Write('REMARK 250   NUMBERS OF POWDER PATTERN POINTS  :  xxxx')                         
71            self.Write('REMARK 250   NUMBERS OF REFLECTIONS            :  xxxx')                         
72            self.Write('REMARK 250   TOTAL NUMBER OF POWDER POINTS     :  xxxx')                         
73            self.Write('REMARK 250')
74            self.Write('REMARK 250  NUMBER OF NON-HYDROGEN ATOMS USED IN REFINEMENT.')                   
75            self.Write('REMARK 250   PROTEIN ATOMS       :      xxxx')                                             
76            self.Write('REMARK 250   NUCLEIC ACID ATOMS  :      xxxx')                                             
77            self.Write('REMARK 250   HETEROGEN ATOMS     :      xxxx')                                             
78            self.Write('REMARK 250   SOLVENT ATOMS       :      xxxx')                                             
79            self.Write('REMARK 250')
80            self.Write('REMARK 250  MODEL REFINEMENT.')                                                   
81            self.Write('REMARK 250   NUMBER OF LEAST-SQUARES PARAMETERS :  xxxx')                         
82            self.Write('REMARK 250   NUMBER OF RESTRAINTS               :  xxxx')                         
83            self.Write('REMARK 250')
84            self.Write('REMARK 250  RMS DEVIATIONS FROM RESTRAINT TARGET VALUES. NUMBER.')               
85            self.Write('REMARK 250   BOND ANGLES                      (DEG) : x.xx   xxx')               
86#            self.Write('REMARK 250   ANTI-BUMPING DISTANCE RESTRAINTS   (A) :x.xxx   xxx')               
87#            self.Write('REMARK 250   HYDROGEN BOND DISTANCE RESTRAINTS  (A) :x.xxx   xxx')               
88            self.Write('REMARK 250   INTERATOMIC DISTANCES              (A) :x.xxx   xxx')               
89            self.Write('REMARK 250   DISTANCES FROM RESTRAINT PLANES    (A) :x.xxx   xxx')               
90            self.Write('REMARK 250   TORSION PSEUDOPOTENTIAL RESTRAINTS (E) : x.xx   xxx')               
91            self.Write('REMARK 250   TORSION ANGLE RESTRAINTS           (E) : x.xx   xxx')               
92            self.Write('REMARK 250')
93            self.Write('REMARK 200')                                                                     
94            self.Write('DBREF')
95           
96        def PDBseqres(seqList):
[3136]97            chains = list(seqList.keys())
[1299]98            chains.sort()
99            nSeq = 0
100            for chain in chains:
101                nres = len(seqList[chain])
[3200]102                nrec = (nres-1)//13+1
[1299]103                iB = 0
104                for irec in range(nrec):
105                    iF = min(iB+13,nres)
106                    text = 'SEQRES {:3d}{:2s}{:5d}  '+(iF-iB)*'{:4s}'
107                    self.Write(text.format(irec+1,chain,nres,*seqList[chain][iB:iF]))
108                    nSeq += 1
109                    iB += 13
110            return nSeq
111           
112        # the export process starts here
113        self.InitExport(event)
114        # load all of the tree into a set of dicts
115        self.loadTree()
116        # create a dict with refined values and their uncertainties
117        self.loadParmDict()
118        if self.ExportSelect():    # set export parameters; ask for file name
119            return
120        filename = self.filename
121        for phasenam in self.phasenam:
122            phasedict = self.Phases[phasenam] # pointer to current phase info
123            General = phasedict['General']
124            if General['Type'] != 'macromolecular':
[3136]125                print ('phase '+phasenam+' not macromolecular, skipping')
[1299]126                continue
127            i = self.Phases[phasenam]['pId']
128            if len(self.phasenam) > 1: # if more than one filename is included, add a phase #
129                self.filename = os.path.splitext(filename)[1] + "_" + str(i) + self.extension
130            fp = self.OpenFile()
131            Atoms = phasedict['Atoms']
132            cx,ct,cs,cia = General['AtomPtrs']
133            seqList = {}
134            AA3letter = ['ALA','ARG','ASN','ASP','CYS','GLN','GLU','GLY','HIS','ILE',
135                'LEU','LYS','MET','PHE','PRO','SER','THR','TRP','TYR','VAL','MSE']
136            seq = 0
[4415]137            notProt = True
[1299]138            for atom in Atoms:
139                if atom[ct-3] in AA3letter and int(atom[ct-4]) != seq:
[4415]140                    notProt = False
[1299]141                    if atom[ct-2] not in seqList:
142                        seqList[atom[ct-2]] = []
143                    seqList[atom[ct-2]].append(atom[ct-3])
144                    seq = int(atom[ct-4])
145            PDBheader()
146            PDBremark250()
147            nSeq = PDBseqres(seqList)
148           
149            # get cell parameters
150            Cell = General['Cell'][1:7]
151            line = "CRYST1 {:8.3f} {:8.3f} {:8.3f} {:6.2f} {:6.2f} {:6.2f} ".format(*Cell)
152            line += General['SGData']['SpGrp'].ljust(13)
153            line += '%2d'%(len(General['SGData']['SGOps'])*len(General['SGData']['SGCen']))
154            self.Write(line)
155            self.Write('ORIGX1      1.000000  0.000000  0.000000        0.00000')
156            self.Write('ORIGX2      0.000000  1.000000  0.000000        0.00000')
157            self.Write('ORIGX3      0.000000  0.000000  1.000000        0.00000')
158            A,B = G2lat.cell2AB(Cell)
159            self.Write('SCALE1     {:9.6f} {:9.6f} {:9.6f}        0.00000'.format(*B[0]))
160            self.Write('SCALE2     {:9.6f} {:9.6f} {:9.6f}        0.00000'.format(*B[1]))
161            self.Write('SCALE3     {:9.6f} {:9.6f} {:9.6f}        0.00000'.format(*B[2]))
162            iatom = 1
163            nHet = 0
164            nTer = 0
165            fmt = '{:6s}{:5d}  {:4s}{:3s} {:1s}{:4s}    '+3*'{:8.3f}'+2*'{:6.2f}'+'{:s}'
166            for atom in Atoms:
167                if atom[cia] == 'I':    #need to deal with aniso thermals for proteins = "ANISOU" records
168                    Biso = atom[cia+1]*8.*np.pi**2
169                xyz = np.inner(A,np.array(atom[cx:cx+3]))
[4415]170                if atom[ct-3] in AA3letter or notProt:
[1299]171                    self.Write(fmt.format('ATOM  ',iatom,atom[ct-1],atom[ct-3].strip(),    \
172                        atom[ct-2].strip(),atom[ct-4].rjust(4),xyz[0],xyz[1],xyz[2],atom[cx+3], \
173                        Biso,atom[ct].rjust(12)))
174                    if atom[ct-1] == 'OXT':
175                        iatom += 1
176                        self.Write('{:6s}{:5d}  {:4s}{:3s}'.format('TER   ',iatom,atom[ct-1],atom[ct-3].strip()))
177                        nTer += 1
178                else:
179                    nHet += 1
180                    self.Write(fmt.format('HETATM',iatom,atom[ct-1],atom[ct-3].strip(),    \
181                        atom[ct-2].strip(),atom[ct-4].rjust(4),xyz[0],xyz[1],xyz[2],atom[cx+3], \
182                        Biso,atom[ct].rjust(12)))
[3245]183                #if atim[cia] == 'a':
184                #   put in 'ANISOU' record
185                #'ANISOU    1  N   ALA A 340     4392   4159   4615    249   -189     73       N' 
[1299]186                iatom += 1
187           
188            vals = [3,0,nHet,0,0,0,6,len(Atoms),nTer,0,nSeq]
189            fmt = 'MASTER'+11*'{:5d}'
190            self.Write(fmt.format(*vals))
191            self.Write('END')
192            self.CloseFile()
[2819]193            print('Phase '+phasenam+' written to PDB file '+self.fullpath)
[1299]194
195class ExportPhaseCartXYZ(G2IO.ExportBaseclass):
196    '''Used to create a Cartesian XYZ file for a phase
197
198    :param wx.Frame G2frame: reference to main GSAS-II frame
199    '''
200    def __init__(self,G2frame):
201        super(self.__class__,self).__init__( # fancy way to say <parentclass>.__init__
202            G2frame=G2frame,
203            formatName = 'Cartesian XYZ',
204            extension='.XYZ',
205            longFormatName = 'Export phase with Cartesian coordinates as .XYZ file'
206            )
207        self.exporttype = ['phase']
208        self.multiple = True
209
210    def Exporter(self,event=None):
211        '''Export as a XYZ file
212        '''
213        # the export process starts here
214        self.InitExport(event)
215        # load all of the tree into a set of dicts
216        self.loadTree()
217        # create a dict with refined values and their uncertainties
218        self.loadParmDict()
219        if self.ExportSelect():    # set export parameters; ask for file name
220            return
221        filename = self.filename
[4573]222        self.OpenFile()
[1299]223        for phasenam in self.phasenam:
224            phasedict = self.Phases[phasenam] # pointer to current phase info
225            General = phasedict['General']
226            i = self.Phases[phasenam]['pId']
227            Atoms = phasedict['Atoms']
228            if not len(Atoms):
[2819]229                print('**** ERROR - Phase '+phasenam+' has no atoms! ****')
[1299]230                continue
231            if len(self.phasenam) > 1: # if more than one filename is included, add a phase #
232                self.filename = os.path.splitext(filename)[1] + "_" + str(i) + self.extension
233            cx,ct,cs,cia = General['AtomPtrs']
234            Cell = General['Cell'][1:7]
235            A,B = G2lat.cell2AB(Cell)
236            fmt = '{:4s}'+3*'{:12.4f}'
237            self.Write('{:6d}'.format(len(Atoms)))
238            self.Write(' ')
239            for atom in Atoms:
240                xyz = np.inner(A,np.array(atom[cx:cx+3]))
241                self.Write(fmt.format(atom[ct],*xyz))
242            self.CloseFile()
[2819]243            print('Phase '+phasenam+' written to XYZ file '+self.fullpath)
[5090]244               
Note: See TracBrowser for help on using the repository browser.