Skip to content

plotting

CCFigure

Generates a figure from a list of tracks

Parameters:

Name Type Description Default
tracks List[CCTrack]

List of tracks to plot. Defaults to None.

None
auto_spacing bool

Automatically add a spacer track between each track. Defaults to False.

False
**kwargs

Additional arguments to pass to the figure

{}
Source code in capcruncher/api/plotting.py
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
class CCFigure:
    """
    Generates a figure from a list of tracks

    Args:
        tracks (List[CCTrack], optional): List of tracks to plot. Defaults to None.
        auto_spacing (bool, optional): Automatically add a spacer track between each track. Defaults to False.
        **kwargs: Additional arguments to pass to the figure
    """

    def __init__(
        self, tracks: List[CCTrack] = None, auto_spacing: bool = False, **kwargs
    ) -> None:
        self.frame = cb.Frame()
        self.auto_spacing = auto_spacing
        self.properties = dict()
        self.properties.update(kwargs)

        if tracks:
            self.tracks = set(tracks)
            self.add_tracks(tracks)
        else:
            self.tracks = set()

    def add_track(self, track: CCTrack) -> None:
        """
        Add a track to the figure

        Args:
            track (CCTrack): Track to add
        """
        self.tracks.add(track)
        self.frame.add_track(track.get_track())

    def add_tracks(self, tracks: List[CCTrack]) -> None:
        """
        Add a list of tracks to the figure

        Args:
            tracks (List[CCTrack]): List of tracks to add
        """
        for track in tracks:
            if self.auto_spacing:
                spacer = CCTrack(None, file_type="spacer")
                self.add_track(spacer.get_track())

            self.add_track(track)

    def plot(
        self,
        gr: Union[str, GenomeRange],
        gr2: Union[str, GenomeRange] = None,
        show: bool = True,
        **kwargs,
    ) -> None:
        """
        Plot the figure

        Args:
            gr (Union[str, GenomeRange]): GenomeRange to plot
            gr2 (Union[str, GenomeRange], optional): Second GenomeRange to plot. Defaults to None.
            show (bool, optional): Show the figure. Defaults to True.
            **kwargs: Additional arguments to pass to the plot
        """

        if gr2:
            fig = self.frame.plot(gr, gr2, **kwargs)
        else:
            fig = self.frame.plot(gr, **kwargs)
        if show:
            fig.show()

        return fig

    def save(
        self,
        gr: Union[str, GenomeRange],
        gr2: Union[str, GenomeRange] = None,
        output: str = None,
        **kwargs,
    ) -> None:
        """
        Plots the figure and saves it to a file

        Args:
            gr (Union[str, GenomeRange]): GenomeRange to plot
            gr2 (Union[str, GenomeRange], optional): Second GenomeRange to plot. Defaults to None.
            output (str, optional): Path to save the figure to. Defaults to None.
            **kwargs: Additional arguments to pass to the plot
        """

        fig = self.plot(gr, gr2, show=False, **kwargs)
        if output:
            fig.savefig(output, dpi=300)
        else:
            fig.savefig(f"{gr.chrom}_{gr.start}_{gr.end}.png", dpi=300)

    @classmethod
    def from_toml(cls, toml_file: os.PathLike, **kwargs) -> "CCFigure":
        """
        Instantiate a CCFigure from a toml file

        Args:
            toml_file (os.PathLike): Path to toml file
            **kwargs: Additional arguments to pass to the figure
        """
        import toml

        with open(toml_file) as f:
            config = toml.load(f)

        tracks = []
        for track_name, attr in config.items():
            file = attr.pop("file") if attr.get("file") else None
            track_name = attr.pop("title") if attr.get("title") else track_name
            tracks.append(CCTrack(file, title=track_name, **attr))
        return cls(tracks, **kwargs)

    @classmethod
    def from_frame(cls, frame: cb.Frame, **kwargs) -> "CCFigure":
        """
        Instantiate a CCFigure from a coolbox Frame

        Args:
            frame (cb.Frame): coolbox Frame to instantiate from
            **kwargs: Additional arguments to pass to the figure
        """
        tracks = []
        for track in frame.tracks:
            tracks.append(CCTrack(track.properties["file"], **track.properties))

        return cls(tracks, **kwargs)

    def to_toml(self, output: str = None) -> Union[None, Dict[str, Any]]:
        """
        Save the CCFigure to a toml file

        Args:
            output (str, optional): Path to save the toml file to. Defaults to None.

        Returns:
            Union[None, Dict[str, Any]]: If output is not specified, returns a dict of the toml file

        """

        import toml
        from collections import OrderedDict

        def _get_n_tracks_of_type(config: Dict[str, Dict], track_type: str):
            return sum(1 for t in config.keys() if track_type in t)

        config = OrderedDict()
        for track in self.tracks:
            # Perform conversions for file-less tracks
            if track.properties.get("type") in ["spacer", "scale", "xaxis"]:
                track_type = track.properties.get("type")
                n = _get_n_tracks_of_type(config, track_type)
                config[f"{track_type} {n}"] = track.properties
                config[f"{track_type} {n}"]["file"] = None
            elif track.properties.get("type") == "genes":
                track_type = track.properties.get("type")
                n = _get_n_tracks_of_type(config, track_type)
                config[f"{track_type} {n}"] = track.properties
                config[f"{track_type} {n}"]["file"] = track.path
            else:
                config[track.properties["title"]] = track.properties
                config[track.properties["title"]]["file"] = track.path

        outfile = output if output else "config.toml"

        with open(outfile, "w") as f:
            config_str = toml.dumps(config)
            f.write(config_str)

        if not output:
            return config

add_track(track)

Add a track to the figure

Parameters:

Name Type Description Default
track CCTrack

Track to add

required
Source code in capcruncher/api/plotting.py
1043
1044
1045
1046
1047
1048
1049
1050
1051
def add_track(self, track: CCTrack) -> None:
    """
    Add a track to the figure

    Args:
        track (CCTrack): Track to add
    """
    self.tracks.add(track)
    self.frame.add_track(track.get_track())

add_tracks(tracks)

Add a list of tracks to the figure

Parameters:

Name Type Description Default
tracks List[CCTrack]

List of tracks to add

required
Source code in capcruncher/api/plotting.py
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
def add_tracks(self, tracks: List[CCTrack]) -> None:
    """
    Add a list of tracks to the figure

    Args:
        tracks (List[CCTrack]): List of tracks to add
    """
    for track in tracks:
        if self.auto_spacing:
            spacer = CCTrack(None, file_type="spacer")
            self.add_track(spacer.get_track())

        self.add_track(track)

from_frame(frame, **kwargs) classmethod

Instantiate a CCFigure from a coolbox Frame

Parameters:

Name Type Description Default
frame Frame

coolbox Frame to instantiate from

required
**kwargs

Additional arguments to pass to the figure

{}
Source code in capcruncher/api/plotting.py
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
@classmethod
def from_frame(cls, frame: cb.Frame, **kwargs) -> "CCFigure":
    """
    Instantiate a CCFigure from a coolbox Frame

    Args:
        frame (cb.Frame): coolbox Frame to instantiate from
        **kwargs: Additional arguments to pass to the figure
    """
    tracks = []
    for track in frame.tracks:
        tracks.append(CCTrack(track.properties["file"], **track.properties))

    return cls(tracks, **kwargs)

from_toml(toml_file, **kwargs) classmethod

Instantiate a CCFigure from a toml file

Parameters:

Name Type Description Default
toml_file PathLike

Path to toml file

required
**kwargs

Additional arguments to pass to the figure

{}
Source code in capcruncher/api/plotting.py
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
@classmethod
def from_toml(cls, toml_file: os.PathLike, **kwargs) -> "CCFigure":
    """
    Instantiate a CCFigure from a toml file

    Args:
        toml_file (os.PathLike): Path to toml file
        **kwargs: Additional arguments to pass to the figure
    """
    import toml

    with open(toml_file) as f:
        config = toml.load(f)

    tracks = []
    for track_name, attr in config.items():
        file = attr.pop("file") if attr.get("file") else None
        track_name = attr.pop("title") if attr.get("title") else track_name
        tracks.append(CCTrack(file, title=track_name, **attr))
    return cls(tracks, **kwargs)

plot(gr, gr2=None, show=True, **kwargs)

Plot the figure

Parameters:

Name Type Description Default
gr Union[str, GenomeRange]

GenomeRange to plot

required
gr2 Union[str, GenomeRange]

Second GenomeRange to plot. Defaults to None.

None
show bool

Show the figure. Defaults to True.

True
**kwargs

Additional arguments to pass to the plot

{}
Source code in capcruncher/api/plotting.py
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
def plot(
    self,
    gr: Union[str, GenomeRange],
    gr2: Union[str, GenomeRange] = None,
    show: bool = True,
    **kwargs,
) -> None:
    """
    Plot the figure

    Args:
        gr (Union[str, GenomeRange]): GenomeRange to plot
        gr2 (Union[str, GenomeRange], optional): Second GenomeRange to plot. Defaults to None.
        show (bool, optional): Show the figure. Defaults to True.
        **kwargs: Additional arguments to pass to the plot
    """

    if gr2:
        fig = self.frame.plot(gr, gr2, **kwargs)
    else:
        fig = self.frame.plot(gr, **kwargs)
    if show:
        fig.show()

    return fig

save(gr, gr2=None, output=None, **kwargs)

Plots the figure and saves it to a file

Parameters:

Name Type Description Default
gr Union[str, GenomeRange]

GenomeRange to plot

required
gr2 Union[str, GenomeRange]

Second GenomeRange to plot. Defaults to None.

None
output str

Path to save the figure to. Defaults to None.

None
**kwargs

Additional arguments to pass to the plot

{}
Source code in capcruncher/api/plotting.py
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
def save(
    self,
    gr: Union[str, GenomeRange],
    gr2: Union[str, GenomeRange] = None,
    output: str = None,
    **kwargs,
) -> None:
    """
    Plots the figure and saves it to a file

    Args:
        gr (Union[str, GenomeRange]): GenomeRange to plot
        gr2 (Union[str, GenomeRange], optional): Second GenomeRange to plot. Defaults to None.
        output (str, optional): Path to save the figure to. Defaults to None.
        **kwargs: Additional arguments to pass to the plot
    """

    fig = self.plot(gr, gr2, show=False, **kwargs)
    if output:
        fig.savefig(output, dpi=300)
    else:
        fig.savefig(f"{gr.chrom}_{gr.start}_{gr.end}.png", dpi=300)

to_toml(output=None)

Save the CCFigure to a toml file

Parameters:

Name Type Description Default
output str

Path to save the toml file to. Defaults to None.

None

Returns:

Type Description
Union[None, Dict[str, Any]]

Union[None, Dict[str, Any]]: If output is not specified, returns a dict of the toml file

Source code in capcruncher/api/plotting.py
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
def to_toml(self, output: str = None) -> Union[None, Dict[str, Any]]:
    """
    Save the CCFigure to a toml file

    Args:
        output (str, optional): Path to save the toml file to. Defaults to None.

    Returns:
        Union[None, Dict[str, Any]]: If output is not specified, returns a dict of the toml file

    """

    import toml
    from collections import OrderedDict

    def _get_n_tracks_of_type(config: Dict[str, Dict], track_type: str):
        return sum(1 for t in config.keys() if track_type in t)

    config = OrderedDict()
    for track in self.tracks:
        # Perform conversions for file-less tracks
        if track.properties.get("type") in ["spacer", "scale", "xaxis"]:
            track_type = track.properties.get("type")
            n = _get_n_tracks_of_type(config, track_type)
            config[f"{track_type} {n}"] = track.properties
            config[f"{track_type} {n}"]["file"] = None
        elif track.properties.get("type") == "genes":
            track_type = track.properties.get("type")
            n = _get_n_tracks_of_type(config, track_type)
            config[f"{track_type} {n}"] = track.properties
            config[f"{track_type} {n}"]["file"] = track.path
        else:
            config[track.properties["title"]] = track.properties
            config[track.properties["title"]]["file"] = track.path

    outfile = output if output else "config.toml"

    with open(outfile, "w") as f:
        config_str = toml.dumps(config)
        f.write(config_str)

    if not output:
        return config

CCTrack

Provides a wrapper around tracks to provide a consistent interface

Parameters:

Name Type Description Default
file PathLike

Path to file to plot

required
file_type Literal['heatmap', 'bigwig', 'bigwig_summary', 'scale', 'bed', 'xaxis', 'genes', 'spacer']

Type of file to plot. Defaults to None.

None
**kwargs

Additional arguments to pass to the track

{}
Source code in capcruncher/api/plotting.py
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
class CCTrack:
    """
    Provides a wrapper around tracks to provide a consistent interface

    Args:
        file (os.PathLike): Path to file to plot
        file_type (Literal["heatmap", "bigwig", "bigwig_summary", "scale", "bed", "xaxis", "genes", "spacer"], optional): Type of file to plot. Defaults to None.
        **kwargs: Additional arguments to pass to the track
    """

    def __init__(
        self,
        file,
        file_type: Literal[
            "heatmap",
            "heatmap_summary",
            "bigwig",
            "bigwig_summary",
            "scale",
            "bed",
            "xaxis",
            "genes",
            "spacer",
        ] = None,
        **kwargs,
    ):
        self.file = file
        self.properties = dict()
        self.properties.update(kwargs)

        if file_type:
            self.properties["type"] = file_type
        elif self.properties.get("type"):
            pass
        else:
            raise ValueError(
                "Please specify file_type as one of: heatmap, bigwig, bigwig_summary, scale, bed, xaxis, genes, spacer"
            )

    def get_track(self):
        match self.properties.get("type"):  # noqa
            case "heatmap":
                assert (
                    "binsize" in self.properties
                ), "Binsize must be specified for heatmap track (e.g. binsize=5000)"
                return CCMatrix(self.file, **self.properties)
            case "heatmap_summary":
                assert (
                    "binsize" in self.properties
                ), "Binsize must be specified for heatmap track (e.g. binsize=5000)"

                matricies = []
                for matrix in self.file:
                    matricies.append(CCMatrix(matrix, **self.properties))

                return CCAverageMatrix(matricies, **self.properties)
            case "bigwig":
                if self.properties.get("overlay"):
                    return cb.BigWigCoverage(self.file, **self.properties)
                else:
                    return CCBigWig(self.file, **self.properties)
            case "bigwig_summary":
                return CCBigWigCollection(self.file, **self.properties)
            case "scale":
                return ScaleBar(**self.properties)
            case "bed":
                return CCSimpleBed(self.file, **self.properties)
            case "xaxis":
                return CCXAxisGenomic(**self.properties)
            case "genes":
                if self.properties.get("title"):
                    del self.properties["title"]
                return cb.BED(self.file, **self.properties)
            case "spacer":
                return cb.Spacer(**self.properties)
            case _:
                if getattr(cb, self.properties.get("type")):
                    return getattr(cb, self.properties.get("type"))(
                        self.file, **self.properties
                    )

                else:
                    raise ValueError(
                        f"Unknown track type {self.properties.get('type')}, select from: heatmap, bigwig, bigwig_summary, scale, bed, xaxis, genes, spacer"
                    )

    @property
    def path(self) -> str:
        if isinstance(self.file, (list, tuple, np.ndarray)):
            return [str(pathlib.Path(f).resolve()) for f in self.file]
        else:
            return str(pathlib.Path(self.file).resolve())

    def __repr__(self) -> str:
        return f"CCTrack({self.properties.get('title')}, {self.properties.get('type')})"