diff --git a/src/iranges/IRanges.py b/src/iranges/IRanges.py index 1d7f98b..b82f54f 100644 --- a/src/iranges/IRanges.py +++ b/src/iranges/IRanges.py @@ -1,7 +1,7 @@ import biocutils as ut from typing import Sequence, Optional, List, Union, Dict from biocframe import BiocFrame -from biocgenerics import combine_seqs, combine_rows +from biocgenerics import combine_seqs, combine_rows, show_as_cell, format_table import numpy as np from copy import deepcopy @@ -357,25 +357,36 @@ def __repr__(self) -> str: Returns: A string representation of this object. """ - message = "IRanges(start=" + ut.print_truncated_list(self._start) + ", " - message += "width=" + ut.print_truncated_list(self._width) + ", " - if self._names: - message += "names=" + ut.print_truncated_list(self._names) - if self._mcols.shape[1] > 0: - message += "mcols=" + repr(self._mcols) - if len(self._metadata): - message += repr(self._metadata) + opt = np.get_printoptions() + old_threshold = opt["threshold"] + old_edgeitems = opt["edgeitems"] + + try: + opt["threshold"] = 50 + opt["edgeitems"] = 3 + message = "IRanges(start=" + repr(self._start) + message += ", width=" + repr(self._width) + if self._names: + message += ", names=" + ut.print_truncated_list(self._names) + if self._mcols.shape[1] > 0: + message += ", mcols=" + repr(self._mcols) + if len(self._metadata): + message += ", metadata=" + repr(self._metadata) + message += ")" + finally: + opt["threshold"] = old_threshold + opt["edgeitems"] = old_edgeitems + return message - def __str__(self): + def __str__(self) -> str: """ Returns: A pretty-printed string representation of this object. """ nranges = len(self) nmcols = self._mcols.shape[1] - # TODO: clean up later. - return ( + output = ( "IRanges object with " + str(nranges) + " range" @@ -384,8 +395,71 @@ def __str__(self): + str(nmcols) + " metadata column" + ("" if nmcols == 1 else "s") + + "\n" ) + added_table = False + if nranges: + if nranges <= 10: + indices = range(nranges) + insert_ellipsis = False + else: + indices = [0, 1, 2, nranges - 3, nranges - 2, nranges - 1] + insert_ellipsis = True + + if self._names is not None: + raw_floating = ut.subset(self._names, indices) + else: + raw_floating = ["[" + str(i) + "]" for i in indices] + if insert_ellipsis: + raw_floating = raw_floating[:3] + [""] + raw_floating[3:] + floating = ["", ""] + raw_floating + + columns = [] + for prop in ["start", "end", "width"]: + data = getattr(self, "get_" + prop)() + showed = show_as_cell(data, indices) + header = [prop, "<" + type(data).__name__ + ">"] + if insert_ellipsis: + showed = showed[:3] + ["..."] + showed[3:] + columns.append(header + showed) + + if self._mcols.shape[1] > 0: + spacer = ["|"] * (len(indices) + insert_ellipsis) + columns.append(["", ""] + spacer) + + for col in self._mcols.get_column_names(): + data = self._mcols.column(col) + showed = show_as_cell(data, indices) + header = [col, "<" + type(data).__name__ + ">"] + minwidth = max(40, len(header[0]), len(header[1])) + for i, y in enumerate(showed): + if len(y) > minwidth: + showed[i] = y[: minwidth - 3] + "..." + if insert_ellipsis: + showed = showed[:3] + ["..."] + showed[3:] + columns.append(header + showed) + + output += format_table(columns, floating_names=floating) + added_table = True + + footer = [] + if len(self._metadata): + footer.append( + "metadata (" + + str(len(self._metadata)) + + "): " + + ut.print_truncated_list( + list(self._metadata.keys()), sep=" ", include_brackets=False + ) + ) + if len(footer): + if added_table: + output += "\n------\n" + output += "\n".join(footer) + + return output + ################# #### Copying #### #################