source: trunk/imports/G2img_HDF5.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: 5.9 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2017-10-23 16:39:16 +0000 (Mon, 23 Oct 2017) $
4# $Author: vondreele $
5# $Revision: 3136 $
6# $URL: trunk/imports/G2img_HDF5.py $
7# $Id: G2img_HDF5.py 3136 2017-10-23 16:39:16Z vondreele $
8########### SVN repository information ###################
9'''
10*Module G2img_HDF5: summed HDF5 image file*
11-------------------------------------------
12
13Reads all images found in a HDF5 file.
14
15'''
16
17from __future__ import division, print_function
18try:
19    import h5py
20except ImportError:
21    h5py = None
22import GSASIIobj as G2obj
23import GSASIIpath
24GSASIIpath.SetVersionNumber("$Revision: 3136 $")
25
26class HDF5_Reader(G2obj.ImportImage):
27    '''Routine to read a HD5 image, typically from APS Sector 6.
28    B. Frosik/SDM.
29    '''
30    dsetlist = []
31    buffer = {}
32    init = False
33
34    def __init__(self):
35        if h5py is None:
36            self.UseReader = False
37            print('HDF5 Reader skipped because h5py library is not installed')
38            import os,sys
39            os.path.split(sys.executable)[0]
40            conda = os.path.join(os.path.split(sys.executable)[0],'conda')
41            if os.path.exists(conda):
42                print('To fix this use command:\n\t'+conda+' install h5py hdf5')
43        super(self.__class__,self).__init__( # fancy way to self-reference
44                                             extensionlist=('.hdf5','.hd5','.h5','.hdf'),
45                                             strictExtension=True,
46                                             formatName = 'HDF5 image',
47                                             longFormatName = 'HDF5 image file'
48                                             )
49
50    def ContentsValidator(self, filename):
51        '''Test if valid by seeing if the HDF5 library recognizes the file.
52        '''
53        try:
54            fp = h5py.File(filename, 'r')
55            fp.close()
56            return True
57        except IOError:
58            return False               
59
60    def Reader(self, filename, ParentFrame=None, **kwarg):
61        '''Scan file structure using :meth:`visit` and map out locations of image(s)
62        then read one image using :meth:`readDataset`. Save map of file structure in
63        buffer arg, if used.
64        '''
65        imagenum = kwarg.get('blocknum')
66        if imagenum is None: imagenum = 1
67        self.buffer = kwarg.get('buffer',{})
68        try:
69            fp = h5py.File(filename, 'r')
70            if not self.buffer.get('init'):
71                self.buffer['init'] = True
72                self.Comments = self.visit(fp)
73                if imagenum > len(self.buffer['imagemap']):
74                    self.errors = 'No valid images found in file'
75                    return False
76               
77            self.Data,self.Npix,self.Image = self.readDataset(fp,imagenum)
78            if self.Npix == 0:
79                self.errors = 'No valid images found in file'
80                return False
81            self.LoadImage(ParentFrame,filename,imagenum)
82            self.repeatcount = imagenum
83            self.repeat = imagenum < len(self.buffer['imagemap'])
84            if GSASIIpath.GetConfigValue('debug'): print('Read image #'+str(imagenum)+' from file '+filename)
85            return True
86        except IOError:
87            print ('cannot open file '+ filename)
88            return False
89        finally:
90            fp.close()
91
92    def visit(self, fp):
93        '''Recursively visit each node in an HDF5 file. For nodes
94        ending in 'data' look at dimensions of contents. If the shape is
95        length 2 or 4 assume an image and index in self.buffer['imagemap']
96        ''' 
97        datakeyword = 'data'
98        head = []
99        def func(name, dset):
100            if not hasattr(dset,'shape'): return # not array, can't be image
101            if isinstance(dset, h5py.Dataset):
102                if len(dset.shape) < 2:
103                    head.append('%s: %s'%(dset.name,str(dset[()][0])))
104                if dset.name.endswith(datakeyword):
105                    dims = dset.shape
106                    if len(dims) == 4:
107                        self.buffer['imagemap'] += [(dset.name,i) for i in range(dims[1])]
108                    elif len(dims) == 3:
109                        self.buffer['imagemap'] += [(dset.name,i) for i in range(dims[0])]
110                    elif len(dims) == 2:
111                        self.buffer['imagemap'] += [(dset.name,None)]
112                    else:
113                        print('Skipping entry '+str(dset.name)+'. Shape is '+str(dims))
114        #if GSASIIpath.GetConfigValue('debug'): print 'visit'
115        self.buffer['imagemap'] = []
116        fp.visititems(func)
117        return head
118       
119    def readDataset(self,fp,imagenum=1):
120        '''Read a specified image number from a file
121        '''
122        name,num = self.buffer['imagemap'][imagenum-1] # look up in map
123        dset = fp[name]
124        if num is None:
125            image = dset[()]
126        elif len(dset.shape) == 4:
127            image = dset[0,num,...]
128        elif len(dset.shape) == 3:
129            image = dset[num,...]
130        else:
131            msg = 'Unexpected image dimensions '+name
132            print(msg)
133            raise Exception(msg)
134        sizexy = list(image.shape) 
135        Npix = sizexy[0]*sizexy[1]
136        data = {'pixelSize':[200.,200.],'wavelength':0.15,'distance':1000.,
137                'center':[sizexy[0]*0.1,sizexy[1]*0.1],'size':sizexy}
138        for item in self.Comments:
139            name,val = item.split(':',1)
140            if 'wavelength' in name and 'spread' not in name:
141                try:
142                    data['wavelength'] = float(val)
143                except ValueError:
144                    pass
145            elif 'distance' in name:
146                data['distance'] = float(val)
147            elif 'x_pixel_size' in name:
148                data['pixelSize'][0] = float(val)*1000.
149            elif 'y_pixel_size' in name:
150                data['pixelSize'][1] = float(val)*1000.
151            elif 'beam_center_x' in name: 
152                data['center'][0] = float(val)
153            elif 'beam_center_y' in name: 
154                data['center'][1] = float(val)               
155        return data,Npix,image.T
Note: See TracBrowser for help on using the repository browser.