Changeset 3187 for trunk/GSASIIIO.py
- Timestamp:
- Dec 10, 2017 10:14:04 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/GSASIIIO.py
r3180 r3187 39 39 import sys 40 40 import re 41 import glob 41 42 import random as ran 42 43 import GSASIIpath … … 363 364 364 365 def GetImageData(G2frame,imagefile,imageOnly=False,ImageTag=None,FormatName=''): 365 '''Read a single image with an image importer. 366 '''Read a single image with an image importer. This is called to reread an image 367 after it has already been imported with :meth:`GSASIIdataGUI.GSASII.OnImportGeneric` 368 (or :func:`ReadImages` in Auto Integration) so it is not necessary to reload metadata. 366 369 367 370 :param wx.Frame G2frame: main GSAS-II Frame and data object. … … 439 442 using image importers. Called only in :meth:`AutoIntFrame.OnTimerLoop`. 440 443 444 ToDo: Images are most commonly read in :meth:`GSASIIdataGUI.GSASII.OnImportGeneric` 445 which is called from :meth:`GSASIIdataGUI.GSASII.OnImportImage` 446 it would be good if these routines used a common code core so that changes need to 447 be made in only one place. 448 441 449 :param wx.Frame G2frame: main GSAS-II Frame and data object. 442 450 :param str imagefile: name of image file … … 492 500 rd.Image = rd.Image.T 493 501 rd.Data['ImageTag'] = rd.repeatcount 502 if GSASIIpath.GetConfigValue('Image_1IDmetadata'): 503 rd.readfilename = imagefile 504 Get1IDMetadata(rd) 494 505 LoadImage2Tree(imagefile,G2frame,rd.Comments,rd.Data,rd.Npix,rd.Image) 495 506 repeat = rd.repeat … … 2135 2146 return Layer 2136 2147 2148 def Read1IDpar(imagefile): 2149 '''Reads image metadata from a 1-ID style .par file from the same directory 2150 as the image. The .par file has any number of columns separated by spaces. 2151 As an index to the .par file a second label file must be specified with the 2152 same file name as the .par file but the extension must be .XXX_lbls (where 2153 .XXX is the extension of the image) or if that is not present extension 2154 .lbls 2155 2156 :param str imagefile: the full name of the image file (with directory and extension) 2157 2158 :returns: a dict with parameter values. Named parameters will have the type based on 2159 the specified Python function, named columns will be character strings 2160 2161 The contents of the label file will look like this:: 2162 2163 # define keywords 2164 filename:lambda x,y: "{}_{:0>6}".format(x,y)|33,34 2165 distance: float | 75 2166 wavelength:lambda keV: 12.398425/float(keV)|9 2167 pixelSize:lambda x: [74.8, 74.8]|0 2168 ISOlikeDate: lambda dow,m,d,t,y:"{}-{}-{}T{} ({})".format(y,m,d,t,dow)|0,1,2,3,4 2169 # define other variables 2170 0:day 2171 1:month 2172 2:date 2173 3:time 2174 4:year 2175 7:I_ring 2176 2177 This file contains three types of lines in any order. 2178 * Named parameters are evaluated with user-supplied Python code (see 2179 subsequent information). Specific named parameters are used 2180 to determine values that are used for image interpretation (see table, 2181 below). Any others are copied to the Comments subsection of the Image 2182 tree item. 2183 * Column labels are defined with a column number (integer) followed by 2184 a colon (:) and a label to be assigned to that column. All labeled 2185 columns are copied to the Image's Comments subsection. 2186 * Comments are any line that does not contain a colon. 2187 2188 Note that columns are numbered starting at zero. 2189 2190 Any named parameter may be defined provided it is not a valid integer, 2191 but the named parameters in the table have special meanings, as descibed. 2192 The parameter name is followed by a colon. After the colon, specify 2193 Python code that defines or specifies a function that will be called to 2194 generate a value for that parameter. After that code, supply a vertical 2195 bar (|) and then a list of one more more columns that will be supplied 2196 as arguments to that function. The examples above are discussed below: 2197 2198 ``filename:lambda x,y: "{}_{:0>6}".format(x,y)|33,34`` 2199 Here the function to be used is defined with a lambda statement: 2200 2201 lambda x,y: "{}_{:0>6}".format(x,y) 2202 2203 This function will use the format function to create a file name from the 2204 contents of columns 33 and 34. The first parameter (x, col. 33) is inserted directly into 2205 the file name, followed by a underscore (_), followed by the second parameter (y, col. 34), 2206 which will be left-padded with zeros to six characters (format directive ``:0>6``). 2207 2208 ``distance: float | 75`` 2209 Here the contents of column 75 will be converted to a floating point number 2210 by calling float on it. Note that the spaces here are ignored. 2211 2212 ``wavelength:lambda keV: 12.398425/float(keV)|9`` 2213 Here we define an algebraic expression to convert an energy in keV to a 2214 wavelength and pass the contents of column 9 as that input energy 2215 2216 ``pixelSize:lambda x: [74.8, 74.8]|0`` 2217 In this case the pixel size is a constant (a list of two numbers). The first 2218 column is passed as an argument as at least one argument is required, but that 2219 value is not used in the expression. 2220 2221 ``ISOlikeDate: lambda dow,m,d,t,y:"{}-{}-{}T{} ({})".format(y,m,d,t,dow)|0,1,2,3,4`` 2222 This example defines a parameter that takes items in the first five columns 2223 and formats them in a different way. This parameter is not one of the pre-defined 2224 parameter names below. Some external code could be used to change the month string 2225 (argument ``m``) to a integer from 1 to 12. 2226 2227 **Pre-defined parameter names** 2228 2229 ============= ========= ======== ==================================================== 2230 keyword required type Description 2231 ============= ========= ======== ==================================================== 2232 filename yes str generates the file name prefix for the matching image 2233 file (MyImage001 for file /tmp/MyImage001.tif). 2234 polarization no float generates the polarization expected based on the 2235 monochromator angle, defaults to 0.99. 2236 center no list of generates the approximate beam center on the detector 2237 2 floats in mm, such as [204.8, 204.8]. 2238 distance yes float generates the distance from the sample to the detector 2239 in mm 2240 pixelSize no list of generates the size of the pixels in microns such as 2241 2 floats [200.0, 200.0]. 2242 wavelength yes float generates the wavelength in Angstroms 2243 ============= ========= ======== ==================================================== 2244 2245 2246 ''' 2247 dir,fil = os.path.split(os.path.abspath(imagefile)) 2248 imageName,ext = os.path.splitext(fil) 2249 parfiles = glob.glob(os.path.join(dir,'*.par')) 2250 if len(parfiles) == 0: 2251 print('Sorry, No 1-ID .par file found in '+dir) 2252 return {} 2253 for parFil in parfiles: # loop over all .par files (hope just 1) in image dir until image is found 2254 parRoot = os.path.splitext(parFil)[0] 2255 for e in (ext+'_lbls','.lbls'): 2256 if os.path.exists(parRoot+e): 2257 lblFil = parRoot+e 2258 break 2259 else: 2260 print('Warning: No labels definitions found for '+parFil) 2261 return {} 2262 fp = open(lblFil,'Ur') # read column labels 2263 lbldict = {} 2264 fmt = "" 2265 keyExp = {} 2266 keyCols = {} 2267 for line in fp: # read label definitions 2268 items = line.strip().split(':') 2269 if len(items) < 2: continue # no colon, line is a comment 2270 # is this line a definition for a named parameter? 2271 key = items[0] 2272 try: 2273 int(key) 2274 except ValueError: # named parameters are not valid numbers 2275 items = line.split(':',1)[1].split('|') 2276 try: 2277 keyExp[key] = eval(items[0]) # compile the expression 2278 if not callable(keyExp[key]): 2279 raise Exception("Expression not a function") 2280 except Exception as msg: 2281 print('Warning: Expression "{}" is not valid for key {}'.format(items[0],key)) 2282 print(msg) 2283 keyCols[key] = [int(i) for i in items[1].strip().split(',')] 2284 continue 2285 if len(items) == 2: # simple column definition 2286 lbldict[int(items[0])] = items[1] 2287 fp.close() 2288 if 'filename' not in keyExp: 2289 print("Warning: No valid filename expression in {} file, skipping .par".format(lblFil)) 2290 continue 2291 # read the .par, looking for the matching image rootname 2292 fp = open(parFil,'Ur') 2293 for i,line in enumerate(fp): 2294 items = line.strip().split(' ') 2295 name = keyExp['filename'](*[items[j] for j in keyCols['filename']]) 2296 if name == imageName: # got our match, parse the line and finish 2297 metadata = {lbldict[i]:items[i] for i in lbldict} 2298 metadata.update( 2299 {key:keyExp[key](*[items[j] for j in keyCols[key]]) for key in keyExp}) 2300 metadata['par file'] = parFil 2301 metadata['lbls file'] = lblFil 2302 print("Metadata read from {}".format(parFil)) 2303 return metadata 2304 else: 2305 print("Image {} not found in {}".format(imageName,parFil)) 2306 fp.close() 2307 continue 2308 fp.close() 2309 else: 2310 print("Warning: No 1-ID metadata for image {}".format(imageName)) 2311 return {} 2312 2313 def Get1IDMetadata(reader): 2314 '''Add 1-ID metadata to an image using a 1-ID .par file using :func:`Read1IDpar` 2315 2316 :param reader: a reader object from reading an image 2317 2318 ''' 2319 parParms = Read1IDpar(reader.readfilename) 2320 if not parParms: return # check for read failure 2321 specialKeys = ('filename',"polarization", "center", "distance", "pixelSize", "wavelength",) 2322 reader.Comments = ['Metadata from {} assigned by {}'.format(parParms['par file'],parParms['lbls file'])] 2323 for key in parParms: 2324 if key in specialKeys+('par file','lbls file'): continue 2325 reader.Comments += ["{} = {}".format(key,parParms[key])] 2326 if "polarization" in parParms: 2327 reader.Data['PolaVal'][0] = parParms["polarization"] 2328 else: 2329 reader.Data['PolaVal'][0] = 0.99 2330 if "center" in parParms: 2331 reader.Data['center'] = parParms["center"] 2332 if "pixelSize" in parParms: 2333 reader.Data['pixelSize'] = parParms["pixelSize"] 2334 if "wavelength" in parParms: 2335 reader.Data['wavelength'] = parParms['wavelength'] 2336 else: 2337 print('Error: wavelength not defined in {}'.format(parParms['lbls file'])) 2338 if "distance" in parParms: 2339 reader.Data['distance'] = parParms['distance'] 2340 reader.Data['setdist'] = parParms['distance'] 2341 else: 2342 print('Error: distance not defined in {}'.format(parParms['lbls file'])) 2343 2137 2344 if __name__ == '__main__': 2138 2345 import GSASIIdataGUI
Note: See TracChangeset
for help on using the changeset viewer.