<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _series_shaped(self):
 """Return image series in "shaped" file."""

        pages = self.pages
        pages.useframes = True
        lenpages = len(pages)

        def append_series(series, pages, axes, shape, reshape, name,
                          truncated):
            page = pages[0]
            if not axes:
                shape = page.shape
                axes = page.axes
                if len(pages) > 1:
                    shape = (len(pages),) + shape
                    axes = 'Q' + axes
            size = product(shape)
            resize = product(reshape)
            if page.is_contiguous and resize > size and resize % size == 0:
                if truncated is None:
                    truncated = True
                axes = 'Q' + axes
                shape = (resize // size,) + shape
            try:
                axes = reshape_axes(axes, shape, reshape)
                shape = reshape
            except ValueError as exc:
                log.warning('Shaped series: %s: %s',
                            exc.__class__.__name__, exc)
            series.append(
                TiffPageSeries(pages, shape, page.dtype, axes, name=name,
                               kind='Shaped', truncated=truncated))

        keyframe = axes = shape = reshape = name = None
        series = []
        index = 0
        while True:
            if index >= lenpages:
                break
            # new keyframe; start of new series
            pages.keyframe = index
            keyframe = pages.keyframe
            if not keyframe.is_shaped:
                log.warning(
                    'Shaped series: invalid metadata or corrupted file')
                return None
            # read metadata
            axes = None
            shape = None
            metadata = json_description_metadata(keyframe.is_shaped)
            name = metadata.get('name', '')
            reshape = metadata['shape']
            truncated = metadata.get('truncated', None)
            if 'axes' in metadata:
                axes = metadata['axes']
                if len(axes) == len(reshape):
                    shape = reshape
                else:
                    axes = ''
                    log.warning('Shaped series: axes do not match shape')
            # skip pages if possible
            spages = [keyframe]
            size = product(reshape)
            npages, mod = divmod(size, product(keyframe.shape))
            if mod:
                log.warning(
                    'Shaped series: series shape does not match page shape')
                return None
            if 1 < npages <= lenpages - index:
                size *= keyframe._dtype.itemsize
                if truncated:
                    npages = 1
                elif (keyframe.is_final and
                      keyframe.offset + size < pages[index+1].offset):
                    truncated = False
                else:
                    # need to read all pages for series
                    truncated = False
                    for j in range(index+1, index+npages):
                        page = pages[j]
                        page.keyframe = keyframe
                        spages.append(page)
            append_series(series, spages, axes, shape, reshape, name,
                          truncated)
            index += npages

        self.is_uniform = len(series) == 1

        return series