Genomic scores
Genomic scores associate values with genomic positions, alleles, or intervals. GAIn distinguishes three types of genomic scores according to what each record describes:
Type |
What a record represents |
Examples |
|---|---|---|
A genomic position or a run of positions |
Conservation scores such as |
|
An allele or substitution at a genomic position |
Variant-level scores such as |
|
A genomic interval with associated attributes |
CNV collections, ATAC fragments, and region annotations |
All three types share the GenomicScore base class. It provides common functionality for opening and closing score resources, inspecting score definitions, retrieving records, and filtering data. Each specialized class also provides methods appropriate to the genomic features it represents. This chapter covers the shared Python interface. The following chapters describe the three score types individually.
Accessing a genomic score
The build_score_from_resource_id() function builds a genomic score object from a resource ID and a repository:
import gain.grr as grr
repo = grr.build_genomic_resource_repository()
score = grr.build_score_from_resource_id("hg38/scores/phastCons100way", repo)
If you already have a GenomicResource object, use build_score_from_resource() instead:
resource = repo.get_resource("hg38/scores/phastCons100way")
score = grr.build_score_from_resource(resource)
Both functions are available through gain.grr. They determine the score type from the resource definition and return the corresponding PositionScore, AlleleScore, or FragmentScore object. Each type also has its own builder functions, described in the corresponding chapter.
Opening and closing a genomic score
A GenomicScore object is initially closed. It uses an underlying data source, such as a tabix-indexed file, a bigWig, or a VCF, that must be opened before reading scores. Call open() to open the object and close() when you finish. The open() method returns the score object, so it can be chained to a builder function.
A with block closes the score automatically, including when an error occurs inside the block:
with grr.build_score_from_resource_id(
"hg38/scores/phastCons100way", repo
).open() as score:
print(score.get_scores_at_position("chr21", 5_030_000))
The with statement does not open the score automatically, so the .open() call is necessary. Attempting to read a closed score raises ValueError: genomic score <id> is not open. Requiring an explicit open() call makes the cost of initializing a score clear and helps prevent file handles from being left open. You can check whether a score is open using is_open(). This behavior applies to all three genomic score types.
Score definitions
A genomic score resource can provide one or more scores. The resource definition describes these in a scores: block, as explained in the Scores section of the GRR documentation.
In Python, each declared score is represented by a GenomicScoreDef object. It contains information such as the score ID, value type, rules for converting values read from the data file, and the associated histogram configuration. Score definitions can be inspected through score.score_definitions or retrieved individually with get_score_definition():
for score_def in score.score_definitions.values():
print(score_def.score_id, score_def.value_type)
one = score.get_score_definition("phastCons100way")
parse_value() converts an individual raw value to its declared type. parse_array() performs the same conversion on an array of values. The array method supports efficient reads of large regions without constructing a separate Python object for every record.
Chromosome names and lengths
get_all_chromosomes() returns the contigs represented in the score’s data, in the order stored in the table. has_chromosome() checks whether a particular contig is present.
Chromosome lengths can come from several sources. GAIn may use the reference genome associated with the score, the header of a bigWig file, an estimate from a tabix index, or the extent of records in an in-memory table. These sources are identified by ChromLengthSource. A length obtained from a reference genome or bigWig header can describe the complete chromosome, whereas a tabix estimate provides an upper bound derived from the indexed data rather than the true chromosome length.
By default, GAIn selects the best available source. You can inspect the available sources with chrom_length_sources, request a specific source, and determine which source supplied a result:
with grr.build_score_from_resource_id(
"hg38/scores/phastCons100way", repo
).open() as score:
print(score.chrom_length_sources)
print(score.get_chrom_length("chr21"))
print(score.get_chrom_length_source("chr21"))
print(score.get_chrom_length("chr21", source="tabix_estimate"))
print(score.get_all_chrom_lengths(source="reference_genome"))
get_all_chrom_lengths() returns lengths for the contigs covered by the requested source. The reference-genome lengths reach the score through the statistics/chrom_lengths.json file created during repository repair. If a resource was repaired before that file was introduced, it may have only table-derived lengths until grr_manage repo-repair is run again. Requesting the unavailable reference_genome source then raises a ValueError.
A ValueError is also raised when a chromosome-length operation cannot provide an answer, for example when the score is closed, the contig is absent from the score, the requested source has no length for it, or no available source can determine its length.
Reading score records and arrays
fetch_records() yields the records in a genomic region, one at a time. This is the general interface for reading the underlying score data.
For score types and backends that support it, fetch_region_value_arrays() retrieves entire columns as arrays instead of returning a separate record for each row. This is useful when working with large numbers of score values. Before using it, check supports_region_value_arrays() for the scores you want to retrieve. Support depends on the requested value types as well as the underlying data backend.
The position, allele, and fragment score chapters describe methods for retrieving score values at specific genomic locations.
Filtering scores
compile_filter() converts a boolean expression involving the score’s columns into a ScoreFilter object. This filter can be passed to read methods through the score_filter argument, so that records are selected as they are read.
For example, the following code selects records with a phastCons100way score greater than 0.9:
with grr.build_score_from_resource_id(
"hg38/scores/phastCons100way", repo
).open() as score:
keep = score.compile_filter("phastCons100way > 0.9")
for record in score.fetch_records(
"chr21", 5_030_000, 5_040_000, score_filter=keep
):
print(record)
Each filter is associated with the score object that created it. A filter compiled for one score cannot be used with another score object, even when their columns have the same names.
Aggregating scores across regions
Allele and fragment scores provide methods for aggregating the values found in a genomic region. These methods are get_allele_scores_in_region_agg() and get_fragment_scores_overlapping_region_agg(). They process the matching records in a single traversal and return an AlleleAggregate or FragmentAggregate object, respectively.
Each aggregate contains the reduced values and information about the records used to calculate them. For allele scores, this includes the matched allele keys, when the call asks for them with the allele_keys argument. For fragment scores, it includes the number of fragments. Keeping these results together ensures that the values and accompanying information describe the same set of records.
The values are returned in the order of the aggregation queries, rather than indexed by score ID. For example, requesting the same score with two different aggregators produces two values, one for each query. The allele and fragment score chapters describe their aggregation methods in more detail.
Score histograms
A genomic score may have a histogram describing the distribution of its values. The get_score_histogram() method retrieves the histogram associated with a score:
hist = score.get_score_histogram("phastCons100way")
The result may be a numeric, categorical, or null histogram. These types are described in Reading a number histogram, Reading a categorical histogram, and Reading a null histogram. Check the histogram type before using attributes specific to that type.
When a resource defines only one score, the score ID can be omitted from get_score_histogram(), get_histogram_config(), get_score_range(), and the two methods that retrieve histogram image URLs. These methods then use that resource’s single score automatically. The dedicated Histograms chapter explains histogram configurations, contents, and retrieval in more detail.
API
GenomicScore is defined in the module
gain.genomic_resources.genomic_scores.base and is imported from the
package gain.genomic_resources.genomic_scores. GenomicScoreDef is
defined in the module gain.genomic_resources.score_def. ScoreFilter is
defined in the module gain.genomic_resources.score_filter. GenomicScore
is also exported by gain.grr, as grr.GenomicScore. The generic
builders build_score_from_resource_id and build_score_from_resource
are defined in the module gain.genomic_resources.genomic_scores.builders
and are imported from the package gain.genomic_resources.genomic_scores.
They are also exported by gain.grr, as
grr.build_score_from_resource_id and grr.build_score_from_resource.
|
Build the score of a score resource, whatever its kind. |
|
Build the score of the score resource with a given id. |
|
Base class of the position, allele and fragment scores. |
Return the source of chromosome lengths in the score's own table. |
|
The sources that the score can answer a length from, best first. |
|
Close the underlying table and mark the score not open. |
|
|
Compile a boolean expression into a filter over this score. |
|
Yield the records of a region, optionally filtered. |
Yield |
|
Fetch a region as column arrays, without a record for each row. |
|
|
Return the length of every chromosome. |
Return the chromosome names that the score's table holds. |
|
|
Return the length of a chromosome. |
Return the source that answers |
|
Return the configuration of the score. |
|
Read one score off a record of this score's table. |
|
|
Report whether the score's table carries a chromosome. |
Report whether the score is open. |
|
Open the score for reading and return it. |
|
Report whether |
|
The definition of one score of a genomic score resource. |
|
Turn a whole column of raw cells into values, vectorized. |
|
Turn one raw cell into the value of this score. |
|
A compiled record filter, bound to the score that compiled it. |
|
Refuse the records of a score that did not compile this filter. |
|
Yield the records of |
- build_score_from_resource(resource: GenomicResource) GenomicScore[source]
Build the score of a score resource, whatever its kind.
The function reads the
typeof the resource and calls the factory of that kind. Use the factory of the kind when the type is known. Use this function when the type is not.- Parameters:
resource (GenomicResource) – A resource of type
position_score,allele_scoreorfragment_score. The legacy typecnv_collectionalso names a fragment score.- Returns:
A new
PositionScore,AlleleScoreorFragmentScore. Each call returns a new score that the caller owns, so closing it affects nothing else. The score is closed: callopen()before the first read.- Return type:
- Raises:
ValueError – If the resource is not of a score type, or if it declares a retired type such as
np_score.
- build_score_from_resource_id(resource_id: str, grr: GenomicResourceRepo | None = None) GenomicScore[source]
Build the score of the score resource with a given id.
The function finds the resource in the repository and calls
build_score_from_resource().- Parameters:
resource_id (str) – The id of a score resource in the repository.
grr (GenomicResourceRepo | None, default None) – The repository that resolves
resource_id. When it isNone, the function builds the default repository withbuild_genomic_resource_repository().
- Returns:
A new
PositionScore,AlleleScoreorFragmentScore. The score is closed: callopen()before the first read.- Return type:
- Raises:
FileNotFoundError – If the repository has no resource with this id.
ValueError – If the resource is not of a score type, or if it declares a retired type such as
np_score.
- class GenomicScore(resource: GenomicResource)[source]
Base class of the position, allele and fragment scores.
A genomic score gives access to the values of a genomic resource that attaches scores to places in the genome. The class owns what the three kinds share: the score definitions, the open and close lifecycle, the filter compiler, and the record and column-array reads. A score is built closed, so call
open()before the first read.The data of the resource is a tabix file, a VCF, a bigWig or an in-memory table. A score is not safe for concurrent use.
- Variables:
resource (GenomicResource) – The genomic resource of the score.
resource_id (str) – The id of the resource.
config (dict) – The validated and normalized configuration.
table (GenomicPositionTable) – The table that holds the data.
score_definitions (dict[str, GenomicScoreDef]) – The definitions of the scores, keyed by score id.
table_loaded (bool) –
Truewhile the table is open.DEFAULT_AGGREGATORS (dict[str, str | None]) – The aggregator that each kind of score value gets when its config states none. The value types of a score are the keys. Each kind of score sets it.
See also
PositionScore, AlleleScore, FragmentScore
- property chrom_length_source: ChromLengthSource
Return the source of chromosome lengths in the score’s own table.
The answer is known without opening the table, so it works on a score that is not open.
- property chrom_length_sources: list[ChromLengthSource]
The sources that the score can answer a length from, best first.
The sources of the stored lengths file, or the source of the table alone. Reading the property on a score that is not open raises
ValueError.
- close() None[source]
Close the underlying table and mark the score not open.
open()can run again afterwards. Do not callclosewhile another thread reads the score: a reader that passedis_open()can find the table released. A holder that shares one score across threads must serialise the reads,openandcloseitself.
- compile_filter(expression: str) ScoreFilter[source]
Compile a boolean expression into a filter over this score.
The expression names scores of this resource and relates them with
>,>=,<,<=,==,!=andin. The relations combine withnot,andandor. Pass the result to a read asscore_filter.- Parameters:
expression (str) – The filter expression, for example
"phastCons100way > 0.9".- Returns:
A filter bound to this score. The reads of another score refuse it.
- Return type:
- Raises:
ScoreFilterError – If the expression does not parse, or if it names a score that the resource does not define.
- fetch_records(chrom: str, pos_begin: int | None, pos_end: int | None, *, score_filter: ScoreFilter | None = None) Generator[tuple[Any, ...], None, None][source]
Yield the records of a region, optionally filtered.
Read the positional fields of a record from its slots (
record[CHROM],record[POS_BEGIN], …). Read a score value withget_score_value_from_record(). The generator checks nothing before the firstnext(): a closed score, an unknown contig and a filter of another score are all reported there, not from the call.- Parameters:
chrom (str) – The chromosome name. It is required. To read every record of the table, use
score.table.get_all_records().pos_begin (int | None) – The start of the region.
Nonemeans no lower bound.pos_end (int | None) – The end of the region.
Nonemeans no upper bound.score_filter (ScoreFilter | None, default None) – A filter from
compile_filter(). When it is notNone, the generator yields only the records that the filter accepts.
- Yields:
Record – The records that overlap the region, in table order. A region without records yields nothing.
- Raises:
ValueError – If the score is not open, or if the table does not hold
chrom.ScoreFilterError – If
score_filterwas compiled by another score.
- fetch_region_segments_scores(chrom: str, pos_begin: int | None = None, pos_end: int | None = None, scores: Sequence[str] | None = None, *, score_filter: ScoreFilter | None = None) Generator[tuple[int, int, list[str | int | float | bool | None]], None, None][source]
Yield
(begin, end, values)for each record that touches a region.A segment is one record at its own extent, not one value for each position. A record on the edge of the region arrives whole. To answer a question about the window, clip the segments with
gain.genomic_resources.genomic_scores.records.clip_span.- Parameters:
chrom (str) – The chromosome name.
pos_begin (int | None, default None) – The start of the region.
Nonemeans no lower bound.pos_end (int | None, default None) – The end of the region.
Nonemeans no upper bound.scores (Sequence[str] | None, default None) – The ids of the scores to read.
Nonemeans every score of the resource.score_filter (ScoreFilter | None, default None) – A filter from
compile_filter(). The filter reads the whole record, so it can name a score outsidescores.
- Returns:
The segments, in table order. The values follow the order of
scores. A region without records yields nothing.- Return type:
Generator[tuple[int, int, list[ScoreValue]], None, None]
- Raises:
ValueError – If the score is not open, if the table does not hold
chrom, or if a score id is unknown. The call raises these errors.ScoreFilterError – If
score_filterwas compiled by another score. The firstnext()raises this error, not the call.
- fetch_region_value_arrays(chrom: str, pos_begin: int | None, pos_end: int | None, scores: list[str], *, batch_size: int = 100000) Generator[tuple[ndarray, ndarray, dict[str, ndarray]], None, None][source]
Fetch a region as column arrays, without a record for each row.
The bulk form of
fetch_records(), for a caller that scans a whole region and wants columns. Callsupports_region_value_arrays()first. The method checks its arguments when it is called, not at the firstnext().The values are parsed by
parse_array(). The dtype of an array follows the value type of the score, not the backend: afloatorintscore givesfloat64withnanfor no value, and astrscore gives anobjectarray withNone. The method does not clip: a record that overlaps the start of the region arrives whole.- Parameters:
chrom (str) – The chromosome name.
pos_begin (int | None) – The start of the region.
Nonemeans no lower bound.pos_end (int | None) – The end of the region.
Nonemeans no upper bound.scores (list[str]) – The ids of the scores to read. Each id gets an array of its own.
batch_size (int, default 100000) – A hint for the rows of a batch. It is a ceiling: a batch also stays within a budget of raw cells, so a read of many scores gets fewer rows. A bigWig backend sizes its batches itself and ignores the hint.
- Returns:
Batches of
(pos_begin, pos_end, {score_id: values}). The first two items are one-based position arrays. The generator yields nothing for a region without records.- Return type:
Generator[RecordArrays, None, None]
- Raises:
TypeError – If
supports_region_value_arrays()isFalseforscores.ValueError – If the score is not open, or if the table does not hold
chrom.
- get_all_chrom_lengths(source: ChromLengthSource | str | None = None) dict[str, int][source]
Return the length of every chromosome.
- Parameters:
source (ChromLengthSource | str | None, default None) – The source to answer from, or its string value.
Nonemeans the best-ranked source for each chromosome.- Returns:
The lengths, keyed by chromosome in table order. A chromosome that the chosen view cannot answer is left out. The dict is empty if no chromosome has an answer.
- Return type:
dict[str, int]
- Raises:
ValueError – If the score is not open, if
sourceis none of the four sources, or ifsourceisreference_genomeon a score with no stored lengths.
- get_all_chromosomes() list[str][source]
Return the chromosome names that the score’s table holds.
- Returns:
The names, in table order.
- Return type:
list[str]
- Raises:
ValueError – If the score is not open.
- get_chrom_length(chrom: str, source: ChromLengthSource | str | None = None) int[source]
Return the length of a chromosome.
The best-ranked source answers by default. The source tells how far to trust the number: only the reference genome and a bigWig header are exact.
get_chrom_length_source()says which source answered.- Parameters:
chrom (str) – The chromosome name.
source (ChromLengthSource | str | None, default None) – The source to answer from, or its string value.
Nonemeans the best-ranked source.
- Returns:
The length of
chrom.- Return type:
int
- Raises:
ValueError – If the score is not open, if the table does not hold
chrom, ifsourceis none of the four sources, if the source has no answer forchrom, or if no source can measurechrom. Asourceofreference_genomeraises on a score whose repair did not store the lengths.
- get_chrom_length_source(chrom: str) ChromLengthSource[source]
Return the source that answers
get_chrom_length().- Parameters:
chrom (str) – The chromosome name.
- Returns:
The best-ranked source that has an answer for
chrom.- Return type:
ChromLengthSource
- Raises:
ValueError – For the same reasons as
get_chrom_length(), including a chromosome that no source answers.
- get_config() dict[str, Any][source]
Return the configuration of the score.
- Returns:
The configuration of the resource, as validated and normalized when the score was built. It is the object the score holds, not a copy.
- Return type:
dict[str, Any]
- get_score_value_from_record(record: tuple[Any, ...], score_id: str) str | int | float | bool | None[source]
Read one score off a record of this score’s table.
- Parameters:
record (Record) – A record from
fetch_records()of this score.score_id (str) – The id of a score of the resource.
- Returns:
The parsed value.
Noneif the cell holds no value: a missing cell, an NA sentinel of the score, or a cell that does not parse.- Return type:
ScoreValue
- Raises:
KeyError – If the resource does not define
score_id.
- has_chromosome(chrom: str) bool[source]
Report whether the score’s table carries a chromosome.
- Parameters:
chrom (str) – The chromosome name.
- Returns:
Trueif the table holdschrom,Falseotherwise.- Return type:
bool
- Raises:
ValueError – If the score is not open.
- open() Self[source]
Open the score for reading and return it.
Call
openbefore the first read. Entering awithblock does not open the score. Opening an open score does nothing.- Returns:
This score, so the call can chain:
score.open().- Return type:
- Raises:
ValueError – If the score definitions do not fit the table, for example when a configured column does not exist.
- supports_region_value_arrays(scores: list[str]) bool[source]
Report whether
fetch_region_value_arrays()serves these scores.The answer is
Trueonly if the backend serves the column-array read and every named score has a value type that the array parse supports. The method works on a score that is not open.- Parameters:
scores (list[str]) – The ids of the scores to read.
- Returns:
Trueiffetch_region_value_arrays()accepts these scores.Falseif the backend has no array read, if a score id is unknown, or if a score has a value type that the parse does not support. An empty list gives the answer of the backend alone.- Return type:
bool
- class GenomicScoreDef(score_id: str, value_type: str, desc: str, small_values_desc: str | None, large_values_desc: str | None, hist_conf: HistogramConfig | None, aggregator: str | None, col_name: str | None, col_index: int | None, value_parser: Any, na_values: Any)[source]
The definition of one score of a genomic score resource.
Each entry of the
scores:block of a resource becomes one definition. The definition knows the id, the value type and the description of a score, how to turn a raw cell into a value, and which histogram configuration belongs to it. Read the definitions fromGenomicScore.score_definitions.- Variables:
score_id (str) – The id of the score.
value_type (str) – The type of the values:
float,int,strorbool.desc (str) – The description of the score.
small_values_desc (str | None) – The description of the small values.
large_values_desc (str | None) – The description of the large values.
hist_conf (HistogramConfig | None) – The histogram configuration.
aggregator (str | None) – The aggregator that reduces several values for one annotatable to one. It is
Noneuntil the resource type fills its default.number_mismatch_warned (bool) – Internal.
Trueafter a VCF INFO field with a wrong value count was reported once.empty_element_warned (bool) – Internal.
Trueafter an empty element of a multi-valued VCF INFO field was reported once.
- parse_array(cells: ndarray) ndarray[source]
Turn a whole column of raw cells into values, vectorized.
The result equals
[parse_value(c) for c in cells], with the non-value shown in a form that the array can hold. The result has one of two shapes, chosen byvalue_type. Afloatorintscore gives afloat64array withnanfor no value. Astrscore gives anobjectarray withNonefor no value.- Parameters:
cells (np.ndarray) – The raw cells of one column.
- Returns:
The parsed values, one for each cell. The array of an empty column is empty.
- Return type:
np.ndarray
- Raises:
TypeError – If
value_typeis notfloat,intorstr. AskGenomicScore.supports_region_value_arraysfirst.
- parse_value(value: str | int | float | None) str | int | float | bool | None[source]
Turn one raw cell into the value of this score.
- Parameters:
value (str | int | float | None) – The raw cell.
- Returns:
The parsed value.
Noneif the cell isNone(for example an absent VCF INFO key), if it is an NA sentinel of the score, or if it does not parse. A cell that does not parse is logged and skipped, so one bad cell does not abort a scan.- Return type:
ScoreValue
- class ScoreFilter(score: GenomicScore, expression: str, predicate: Callable[[Record], bool])[source]
A compiled record filter, bound to the score that compiled it.
Get a filter from
GenomicScore.compile_filter()and pass it to a read asscore_filter. The filter works only on the records of the score that compiled it.- Variables:
score (GenomicScore) – The score that compiled the filter.
expression (str) – The source expression. Error messages and
reprshow it.
- require_owner(score: GenomicScore) None[source]
Refuse the records of a score that did not compile this filter.
- Parameters:
score (GenomicScore) – The score whose records the caller is about to read.
- Raises:
ScoreFilterError – If
scoreis not the score that compiled the filter.
- select(score: GenomicScore, records: Iterable[Record]) Iterator[Record][source]
Yield the records of
scorethat this filter accepts.- Parameters:
score (GenomicScore) – The score that the records come from.
records (Iterable[Record]) – The records to test.
- Returns:
The accepted records, in the order of
records. The iterator is lazy. It is empty if the filter accepts none.- Return type:
Iterator[Record]
- Raises:
ScoreFilterError – If
scoredid not compile the filter. The call raises the error before any record is read.