def _write_log_pass_content_in_html( logical_file: LogicalFile.LogicalFile, xhtml_stream: XmlWrite.XhtmlStream, # Used for anchor logical_file_index: int, number_of_preceeding_eflrs: int, *, frame_slice: Slice.Slice) -> typing.Tuple[HTMLFrameArraySummary]: assert logical_file.has_log_pass ret = [] lp: LogPass.LogPass = logical_file.log_pass frame_array: LogPass.FrameArray for fa, frame_array in enumerate(lp.frame_arrays): anchor = _anchor(logical_file_index, number_of_preceeding_eflrs, fa) with XmlWrite.Element(xhtml_stream, 'a', {'id': anchor}): pass with XmlWrite.Element(xhtml_stream, 'h3'): xhtml_stream.characters( f'Frame Array: {stringify.stringify_object_by_type(frame_array.ident)} [{fa}/{len(lp.frame_arrays)}]' ) ret.append( _write_frame_array_in_html( logical_file, frame_array, frame_slice, anchor, xhtml_stream, )) return tuple(ret)
def html_write_file_info(path_in: str, xhtml_stream: XmlWrite.XhtmlStream) -> None: with XmlWrite.Element(xhtml_stream, 'h2'): xhtml_stream.characters('File information') table = [ ['KEY', 'VALUE'], ['File Path:', path_in], ['File size:', f'{os.path.getsize(path_in):,d}'], ] html_write_table(table, xhtml_stream, class_style='monospace')
def _write_x_axis_summary(x_axis: XAxis.XAxis, xhtml_stream: XmlWrite.XhtmlStream) -> None: # Parent section is heading h3 # with XmlWrite.Element(xhtml_stream, 'h4'): # xhtml_stream.characters('X Axis summary (all IFLRs)') with XmlWrite.Element(xhtml_stream, 'h4'): xhtml_stream.characters('X Axis') units = x_axis.units.decode('ascii') x_axis_table = [ ['X Axis', 'Value'], ['Channel', f'{x_axis.ident}'], ['Long Name', f'{x_axis.long_name.decode("ascii")}'], ['Minimum', f'{x_axis.summary.min} [{units}]'], ['Maximum', f'{x_axis.summary.max} [{units}]'], ['Frame Count', f'{x_axis.summary.count}'], ] html_write_table(x_axis_table, xhtml_stream, class_style='monospace') with XmlWrite.Element(xhtml_stream, 'h4'): xhtml_stream.characters('X Axis Spacing') with XmlWrite.Element(xhtml_stream, 'p'): xhtml_stream.characters(f'Definitions: {XAxis.SPACING_DEFINITIONS}') x_spacing_table = [ ['X Axis Spacing', 'Value'], ] if x_axis.summary.spacing is not None: spacing = x_axis.summary.spacing x_spacing_table.append(['Minimum', f'{spacing.min} [{units}]']) x_spacing_table.append(['Mean', f'{spacing.mean} [{units}]']) x_spacing_table.append(['Median', f'{spacing.median} [{units}]']) x_spacing_table.append(['Maximum', f'{spacing.max} [{units}]']) if spacing.median != 0: x_spacing_table.append([ 'Range', f'{spacing.max - spacing.min} ({(spacing.max - spacing.min) / spacing.median:%}) [{units}]' ]) else: x_spacing_table.append( ['Range', f'{spacing.max - spacing.min} [{units}]']) x_spacing_table.append(['Std. Dev.', f'{spacing.std} [{units}]']) x_spacing_table.append( ['Count of Normal', f'{spacing.counts.norm:,d}']) x_spacing_table.append( ['Count of Duplicate', f'{spacing.counts.dupe:,d}']) x_spacing_table.append( ['Count of Skipped', f'{spacing.counts.skip:,d}']) x_spacing_table.append(['Count of Back', f'{spacing.counts.back:,d}']) html_write_table(x_spacing_table, xhtml_stream, class_style='monospace') if x_axis.summary.spacing is not None: with XmlWrite.Element(xhtml_stream, 'p'): xhtml_stream.characters('Frame spacing frequency:') with XmlWrite.Element(xhtml_stream, 'pre'): xhtml_stream.characters(x_axis.summary.spacing.histogram_str())
def html_write_table(table_as_strings: typing.List[typing.List[str]], xhtml_stream: XmlWrite.XhtmlStream, class_style) -> None: if len(table_as_strings): with XmlWrite.Element(xhtml_stream, 'table', {'class': class_style}): with XmlWrite.Element(xhtml_stream, 'tr', {}): for cell in table_as_strings[0]: with XmlWrite.Element(xhtml_stream, 'th', {'class': class_style}): xhtml_stream.characters(cell) for row in table_as_strings[1:]: with XmlWrite.Element(xhtml_stream, 'tr', {}): for cell in row: with XmlWrite.Element(xhtml_stream, 'td', {'class': class_style}): assert isinstance( cell, str ), f'{cell} is not a string but {type(cell)}' xhtml_stream.charactersWithBr(cell)
def html_write_storage_unit_label(sul: StorageUnitLabel.StorageUnitLabel, xhtml_stream: XmlWrite.XhtmlStream) -> None: with XmlWrite.Element(xhtml_stream, 'h2'): xhtml_stream.characters('Storage Unit Label') table = [ ['KEY', 'VALUE'], [ 'Storage Unit Sequence Number:', f'{sul.storage_unit_sequence_number:d}' ], ['DLIS Version:', f'{sul.dlis_version.decode("ascii")}'], [ 'Storage Unit Structure:', f'{sul.storage_unit_structure.decode("ascii")}' ], ['Maximum Record Length:', f'{sul.maximum_record_length:d}'], [ 'Storage Set Identifier:', f'{sul.storage_set_identifier.decode("ascii")}' ], ] html_write_table(table, xhtml_stream, class_style='sul')
def _write_top_level_index_table_body( index_file_path: str, dict_tree: DictTree.DictTreeHtmlTable, xhtml_stream: XmlWrite.XhtmlStream) -> None: strip_out_path = len(os.path.dirname(index_file_path)) + 1 for event in dict_tree.genColRowEvents(): if event == dict_tree.ROW_OPEN: # Write out the '<tr>' element xhtml_stream.startElement('tr', {'class': 'filetable'}) elif event == dict_tree.ROW_CLOSE: # Write out the '</tr>' element xhtml_stream.endElement('tr') else: td_attrs = {'class': 'filetable'} if event.row_span > 1: td_attrs['rowspan'] = f'{event.row_span:d}' if event.col_span > 1: td_attrs['colspan'] = f'{event.col_span:d}' if event.node is None: with XmlWrite.Element(xhtml_stream, 'td', td_attrs): possible_index_file = os.path.join( *event.branch) + os.sep + INDEX_FILE if os.path.exists(possible_index_file): xhtml_stream.comment( f' Writing event branch[-1] with link to {INDEX_FILE} ' ) with XmlWrite.Element( xhtml_stream, 'a', {'href': possible_index_file[strip_out_path:]}): xhtml_stream.characters(f'{str(event.branch[-1])}') else: xhtml_stream.comment( f' Writing event branch[-1] without link to absent {possible_index_file}' ) xhtml_stream.characters(f'{str(event.branch[-1])}') else: node: HTMLResult = event.node with XmlWrite.Element(xhtml_stream, 'td', td_attrs): xhtml_stream.comment(' Writing event.node with link ') with XmlWrite.Element( xhtml_stream, 'a', {'href': f'{node.path_output[strip_out_path:]}'}): xhtml_stream.characters(str(event.branch[-1]))
def html_write_body( logical_file_sequence: LogicalFile.LogicalIndex, frame_slice: Slice.Slice, xhtml_stream: XmlWrite.XhtmlStream, ) -> HTMLBodySummary: """Write out the <body> of the document.""" with XmlWrite.Element(xhtml_stream, 'h1'): xhtml_stream.characters('RP66V1 File Data Summary') html_write_file_info(logical_file_sequence.id, xhtml_stream) html_write_storage_unit_label(logical_file_sequence.storage_unit_label, xhtml_stream) html_write_table_of_contents(logical_file_sequence, xhtml_stream) logical_file_summaries: typing.List[HTMLLogicalFileSummary] = [] logical_file: LogicalFile.LogicalFile for lf, logical_file in enumerate(logical_file_sequence.logical_files): eflr_types: typing.List[bytes] = [] with XmlWrite.Element(xhtml_stream, 'h2'): xhtml_stream.characters( f'Logical File [{lf}/{len(logical_file_sequence.logical_files)}]' ) eflr_position: LogicalFile.PositionEFLR for e, eflr_position in enumerate(logical_file.eflrs): eflr_types.append(eflr_position.eflr.set.type) header = [ f'EFLR: {eflr_position.eflr.set.type.decode("ascii")}', f'Shape: {eflr_position.eflr.shape}' ] with XmlWrite.Element(xhtml_stream, 'a', {'id': f'{_anchor(lf, e)}'}): pass with XmlWrite.Element(xhtml_stream, 'h3'): xhtml_stream.characters(' '.join(header)) with XmlWrite.Element(xhtml_stream, 'p'): xhtml_stream.characters( f'Location: {eflr_position.lrsh_position}') if eflr_position.eflr.set.type == b'FILE-HEADER': obj = eflr_position.eflr.objects[0] with XmlWrite.Element(xhtml_stream, 'p'): xhtml_stream.characters( f'File-Header Object "{obj.name.I.decode("ascii")}" O: {obj.name.O} C: {obj.name.C}:' ) elif eflr_position.eflr.set.type == b'ORIGIN': # Slightly special case with ORIGIN records as they contain the Defining Origin of the Logical File. # [RP66V1 Section 5.2.1 Origin Objects] obj = eflr_position.eflr.objects[0] with XmlWrite.Element(xhtml_stream, 'p'): xhtml_stream.characters( f'Logical File Defining Origin "{obj.name.I.decode("ascii")}" O: {obj.name.O} C: {obj.name.C}:' ) html_write_EFLR_as_table(eflr_position.eflr, xhtml_stream) with XmlWrite.Element(xhtml_stream, 'h3'): xhtml_stream.characters('Log Pass') if logical_file.has_log_pass: with XmlWrite.Element( xhtml_stream, 'a', {'id': f'{_anchor(lf, len(logical_file.eflrs))}'}): pass frame_array_summary = _write_log_pass_content_in_html( logical_file, xhtml_stream, lf, len(logical_file.eflrs), frame_slice=frame_slice, ) logical_file_summaries.append( (HTMLLogicalFileSummary(tuple(eflr_types), frame_array_summary))) else: with XmlWrite.Element(xhtml_stream, 'p'): xhtml_stream.characters('NO Log Pass for this Logical Record') logical_file_summaries.append( (HTMLLogicalFileSummary(tuple(eflr_types), tuple()))) return HTMLBodySummary( logical_file_sequence.storage_unit_label.storage_set_identifier.decode( 'ascii'), tuple(logical_file_summaries), )
def html_write_table_of_contents( logical_file_sequence: LogicalFile.LogicalIndex, xhtml_stream: XmlWrite.XhtmlStream) -> None: """Write out the table of contents.""" with XmlWrite.Element(xhtml_stream, 'h2'): xhtml_stream.characters('Table of Contents') with XmlWrite.Element(xhtml_stream, 'ol'): logical_file: LogicalFile.LogicalFile for index_lf, logical_file in enumerate( logical_file_sequence.logical_files): with XmlWrite.Element(xhtml_stream, 'li'): xhtml_stream.characters( f'Logical File [{index_lf}/{len(logical_file_sequence.logical_files)}]' ) with XmlWrite.Element(xhtml_stream, 'ol'): lrsh_position: File.LogicalRecordPosition eflr: EFLR.ExplicitlyFormattedLogicalRecord for index_eflr, (lrsh_position, eflr) in enumerate(logical_file.eflrs): with XmlWrite.Element(xhtml_stream, 'li'): with XmlWrite.Element( xhtml_stream, 'a', {'href': f'#{_anchor(index_lf, index_eflr)}'}): xhtml_stream.characters( f'{eflr.set.type.decode("ascii")}') xhtml_stream.literal(' ') xhtml_stream.characters(f'Shape: {eflr.shape}') if logical_file.has_log_pass: with XmlWrite.Element(xhtml_stream, 'li'): with XmlWrite.Element( xhtml_stream, 'a', { 'href': f'#{_anchor(index_lf, len(logical_file.eflrs))}' }): xhtml_stream.characters( f'Log Pass with {len(logical_file.log_pass)} Frame Arrays' ) with XmlWrite.Element(xhtml_stream, 'ol'): for index_fa, frame_array in enumerate( logical_file.log_pass): with XmlWrite.Element(xhtml_stream, 'li'): attrs = { 'href': f'#{_anchor(index_lf, len(logical_file.eflrs), index_fa)}' } # xhtml_stream.characters(f'Frame Array:') with XmlWrite.Element( xhtml_stream, 'a', attrs): xhtml_stream.characters( f'{stringify.stringify_object_by_type(frame_array.ident)}' ) xhtml_stream.characters( f' with {len(frame_array.channels)} channels' ) xhtml_stream.characters( f' and {len(logical_file.iflr_position_map[frame_array.ident])} frames' )
def _write_frame_array_in_html( logical_file: LogicalFile.LogicalFile, frame_array: LogPass.FrameArray, frame_slice: typing.Union[Slice.Slice, Slice.Sample], anchor: str, xhtml_stream: XmlWrite.XhtmlStream, ) -> HTMLFrameArraySummary: # Parent section is heading h3 # with XmlWrite.Element(xhtml_stream, 'h4'): # xhtml_stream.characters('Frame Data') iflrs: typing.List[XAxis.IFLRReference] = logical_file.iflr_position_map[ frame_array.ident] if len(iflrs): num_frames = logical_file.populate_frame_array( frame_array, frame_slice, None, ) x_axis: XAxis.XAxis = logical_file.iflr_position_map[frame_array.ident] _write_x_axis_summary(x_axis, xhtml_stream) with XmlWrite.Element(xhtml_stream, 'h4'): xhtml_stream.characters('Frame Analysis') with XmlWrite.Element(xhtml_stream, 'p'): if x_axis.summary.spacing is not None: interval = f'{x_axis.summary.spacing.median:0.3f}' else: interval = 'N/A' xhtml_stream.characters( f'Available frames: {len(iflrs)}' f' X axis from {float(iflrs[0].x_axis):0.3f}' f' to {float(iflrs[-1].x_axis):0.3f}' f' interval {interval}' f' [{stringify.stringify_object_by_type(frame_array.x_axis.units)}]' ) with XmlWrite.Element(xhtml_stream, 'p'): xhtml_stream.characters( f'Frame analysis on {frame_slice.long_str(len(iflrs))} frame(s).' f' Number of frames created: {num_frames}' f' Numpy total memory: {frame_array.sizeof_array:,d} bytes') with XmlWrite.Element(xhtml_stream, 'p'): xhtml_stream.characters( f'RP66V1 Frame size {frame_array.len_input_bytes} (bytes/frame))' f' represented internally as {frame_array.sizeof_frame} (bytes/frame).' ) frame_table = [ [ 'Channel', 'O', 'C', 'Rep Code', 'Dims', 'Count', 'Units', 'Long Name', 'Size', 'Absent', 'Min', 'Mean', 'Std.Dev.', 'Max', 'dtype' ], ] for channel in frame_array.channels: # arr = channel.array arr = AbsentValue.mask_absent_values(channel.array) frame_table.append([ channel.ident.I.decode("ascii"), f'{channel.ident.O}', f'{channel.ident.C}', f'{channel.rep_code:d} ({RepCode.REP_CODE_INT_TO_STR[channel.rep_code]})', stringify.stringify_object_by_type(channel.dimensions), stringify.stringify_object_by_type(channel.count), stringify.stringify_object_by_type(channel.units), stringify.stringify_object_by_type(channel.long_name), f'{arr.size:d}', # NOTE: Not the masked array! f'{AbsentValue.count_of_absent_values(channel.array):d}', f'{arr.min():.3f}', f'{arr.mean():.3f}', f'{arr.std():.3f}', f'{arr.max():.3f}', f'{arr.dtype}', ]) html_write_table(frame_table, xhtml_stream, class_style='monospace') x_axis_start = iflrs[0].x_axis x_axis_stop = iflrs[-1].x_axis else: with XmlWrite.Element(xhtml_stream, 'p'): xhtml_stream.characters('No frames.') x_axis_start = x_axis_stop = 0.0 return HTMLFrameArraySummary( frame_array.ident.I, len(iflrs), tuple(c.ident.I for c in frame_array.channels), x_axis_start, x_axis_stop, frame_array.x_axis.units, anchor, )