source: trunk/exports/G2export_PDB.py @ 3136

Last change on this file since 3136 was 3136, checked in by vondreele, 4 years ago

make GSAS-II python 3.6 compliant & preserve python 2.7 use;changes:
do from future import division, print_function for all GSAS-II py sources
all menu items revised to be py 2.7/3.6 compliant
all wx.OPEN --> wx.FD_OPEN in file dialogs
all integer divides (typically for image pixel math) made explicit with ; ambiguous ones made floats as appropriate
all print "stuff" --> print (stuff)
all print >> pFile,'stuff' --> pFile.writeCIFtemplate('stuff')
all read file opens made explicit 'r' or 'rb'
all cPickle imports made for py2.7 or 3.6 as cPickle or _pickle; test for '2' platform.version_tuple[0] for py 2.7
define cPickleload to select load(fp) or load(fp,encoding='latin-1') for loading gpx files; provides cross compatibility between py 2.7/3.6 gpx files
make dict.keys() as explicit list(dict.keys()) as needed (NB: possible source of remaining py3.6 bugs)
make zip(a,b) as explicit list(zip(a,b)) as needed (NB: possible source of remaining py3.6 bugs)
select unichr/chr according test for '2' platform.version_tuple[0] for py 2.7 (G2pwdGUI * G2plot) for special characters
select wg.EVT_GRID_CELL_CHANGE (classic) or wg.EVT_GRID_CELL_CHANGED (phoenix) in grid Bind
maxint --> maxsize; used in random number stuff
raise Exception,"stuff" --> raise Exception("stuff")
wx 'classic' sizer.DeleteWindows?() or 'phoenix' sizer.Clear(True)
wx 'classic' SetToolTipString?(text) or 'phoenix' SetToolTip?(wx.ToolTip?(text)); define SetToolTipString?(self,text) to handle the choice in plots
status.SetFields? --> status.SetStatusText?
'classic' AddSimpleTool? or 'phoenix' self.AddTool? for plot toolbar; Bind different as well
define GetItemPydata? as it doesn't exist in wx 'phoenix'
allow python versions 2.7 & 3.6 to run GSAS-II
Bind override commented out - no logging capability (NB: remove all logging code?)
all import ContentsValidator? open filename & test if valid then close; filepointer removed from Reader
binary importers (mostly images) test for 'byte' type & convert as needed to satisfy py 3.6 str/byte rules

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