"""
Authors:
........
* Henning O. Sorensen & Erik Knudsen
Center for Fundamental Research: Metal Structures in Four Dimensions
Risoe National Laboratory
Frederiksborgvej 399
DK-4000 Roskilde
email:erik.knudsen@risoe.dk
* Jon Wright, ESRF
"""
import logging, sys
logger = logging.getLogger("fileseries")
import traceback as pytraceback
from fabioutils import FilenameObject, next_filename
from openimage import openimage
def new_file_series0(first_object, first=None, last=None, step=1):
"""
[docs] Created from a fabio image
first and last are file numbers
"""
im = first_object
nimages = 0
# for counting images
if None in (first, last):
step = 0
total = 1
else:
total = last - first
yield im
while nimages < total:
nimages += step
try:
newim = im.next()
im = newim
except Exception, error:
pytraceback.print_exc()
# Skip bad images
logger.warning("Got a problem here: %s", error)
try:
im.filename = next_filename(im.filename)
except Exception, error:
# KE: This will not work and will throw an exception
# fabio.next_filename doesn't understand %nnnn on the end
logger.warning("Got another problem here: %s", error)
im.filename = next_filename(im.sequencefilename)
yield None
yield im
def new_file_series(first_object, nimages=0, step=1, traceback=False):
"""
[docs] A generator function that creates a file series starting from a a fabioimage.
Iterates through all images in a file (if more than 1), then proceeds to
the next file as determined by fabio.next_filename.
@param first_object: the starting fabioimage, which will be the first one yielded
in the sequence
@param nimages: the maximum number of images to consider
step: step size, will yield the first and every step'th image until nimages
is reached. (e.g. nimages = 5, step = 2 will yield 3 images (0, 2, 4)
@param traceback: if True causes it to print a traceback in the event of an
exception (missing image, etc.). Otherwise the calling routine can handle
the exception as it chooses
@param yields: the next fabioimage in the series.
In the event there is an exception, it yields the sys.exec_info for the
exception instead. sys.exec_info is a tuple:
( exceptionType, exceptionValue, exceptionTraceback )
from which all the exception information can be obtained.
Suggested usage:
::
for obj in new_file_series( ... ):
if not isinstance(obj, fabio.fabioimage.fabioimage ):
# deal with errors like missing images, non readable files, etc
# e.g.
traceback.print_exception(obj[0], obj[1], obj[2])
"""
im = first_object
nprocessed = 0
abort = False
if nimages > 0:
yield im
nprocessed += 1
while nprocessed < nimages:
try:
newim = im.next()
im = newim
retVal = im
except Exception, ex:
retVal = sys.exc_info()
if(traceback):
pytraceback.print_exc()
# Skip bad images
logger.warning("Got a problem here: next() failed %s", ex)
# Skip bad images
try:
im.filename = next_filename(im.filename)
except Exception, ex:
logger.warning("Got another problem here: next_filename(im.filename) %s", ex)
if nprocessed % step == 0:
yield retVal
# Avoid cyclic references with exc_info ?
retVal = None
if abort: break
nprocessed += 1
class file_series(list):
"""
[docs] Represents a series of files to iterate
has an idea of a current position to do next and prev
You also get from the list python superclass:
append
count
extend
insert
pop
remove
reverse
sort
"""
def __init__(self, list_of_strings):
"""
Constructor:
@param list_of_strings: arg should be a list of strings which are filenames
"""
super(file_series, self).__init__(list_of_strings)
# track current position in list
self._current = 0
# methods which return a filename
def first(self):
"""
[docs] First image in series
"""
return self[0]
def last(self):
"""
[docs] Last in series
"""
return self[-1]
def previous(self):
"""
[docs] Prev in a sequence
"""
self._current -= 1
return self[self._current]
def current(self):
"""Current position in a sequence
[docs]
"""
return self[self._current]
def next(self):
"""
[docs] Next in a sequence
"""
self._current += 1
return self[self._current]
def jump(self, num):
"""
[docs] Goto a position in sequence
"""
assert num < len(self) and num > 0, "num out of range"
self._current = num
return self[self._current]
def len(self):
"""
[docs] Number of files
"""
return len(self)
# Methods which return a fabioimage
def first_image(self):
"""
[docs] First image in a sequence
@return: fabioimage
"""
return openimage(self.first())
def last_image(self):
"""
[docs] Last image in a sequence
@return: fabioimage
"""
return openimage(self.last())
def next_image(self):
"""
[docs] Return the next image
@return: fabioimage
"""
return openimage(self.next())
def previous_image(self):
"""
[docs] Return the previous image
@return: fabioimage
"""
return openimage(self.previous())
def jump_image(self, num):
"""
[docs] Jump to and read image
@return: fabioimage
"""
return openimage(self.jump(num))
def current_image(self):
"""
[docs] Current image in sequence
@return: fabioimage
"""
return openimage(self.current())
# methods which return a file_object
def first_object(self):
"""
[docs] First image in a sequence
@return: file_object
"""
return FilenameObject(self.first())
def last_object(self):
"""
[docs] Last image in a sequence
@return: file_object
"""
return FilenameObject(self.last())
def next_object(self):
"""
[docs] Return the next image
@return: file_object
"""
return FilenameObject(self.next())
def previous_object(self):
"""
[docs] Return the previous image
@return: file_object
"""
return FilenameObject(self.previous())
def jump_object(self, num):
"""
[docs] Jump to and read image
@return: file_object
"""
return FilenameObject(self.jump(num))
def current_object(self):
"""
[docs] Current image in sequence
@return: file_object
"""
return FilenameObject(self.current())
class numbered_file_series(file_series):
"""
[docs] mydata0001.edf = "mydata" + 0001 + ".edf"
mydata0002.edf = "mydata" + 0002 + ".edf"
mydata0003.edf = "mydata" + 0003 + ".edf"
"""
def __init__(self, stem, first, last, extension,
digits=4, padding='Y', step=1):
"""
Constructor
@param stem: first part of the name
@param step: in case of every nth file
@param padding: possibility for specifying that numbers are not padded with zeroes up to digits
"""
if padding == 'Y':
fmt = "%s%0" + str(digits) + "d%s"
else:
fmt = "%s%i%s"
super(numbered_file_series, self).__init__(
[ fmt % (stem, i, extension) for i in range(first,
last + 1,
step) ])
class filename_series:
""" Much like the others, but created from a string filename """
[docs] def __init__(self, filename):
""" create from a filename (String)"""
self.obj = FilenameObject(filename)
def next(self):
""" increment number """
[docs] self.obj.num += 1
return self.obj.tostring()
def previous(self):
""" decrement number """
[docs] self.obj.num -= 1
return self.obj.tostring()
def current(self):
""" return current filename string"""
[docs] return self.obj.tostring()
def jump(self, num):
""" jump to a specific number """
[docs] self.obj.num = num
return self.obj.tostring()
# image methods
def next_image(self):
""" returns the next image as a fabioimage """
[docs] return openimage(self.next())
def prev_image(self):
""" returns the previos image as a fabioimage """
[docs] return openimage(self.previous())
def current_image(self):
""" returns the current image as a fabioimage"""
[docs] return openimage(self.current())
def jump_image(self, num):
""" returns the image number as a fabioimage"""
[docs] return openimage(self.jump(num))
# object methods
def next_object(self):
""" returns the next filename as a fabio.FilenameObject"""
[docs] self.obj.num += 1
return self.obj
def previous_object(self):
""" returns the previous filename as a fabio.FilenameObject"""
[docs] self.obj.num -= 1
return self.obj
def current_object(self):
""" returns the current filename as a fabio.FilenameObject"""
[docs] return self.obj
def jump_object(self, num):
""" returns the filename num as a fabio.FilenameObject"""
[docs] self.obj.num = num
return self.obj