Operations registry

DataAxesFormats.Registry Module

Registering element-wise and reduction operations is required, to allow them to be used in a query.

Note

We do not re-export everything from here to the main Daf namespace, as it is only of interest for implementers of new query operations. Most users of Daf just stick with the (fairly comprehensive) list of built-in query operations so there's no need to pollute their namespace with these detail.

Element-wise operations

DataAxesFormats.Registry.EltwiseOperation Type

Abstract type for all element-wise operations.

In a string query, this is specified using the % operator (e.g., % Abs , % Log base 2 ):

EltwiseOperation := % operation ( parameter value )*

Since each EltwiseOperation isa QueryOperation , you can directly apply it to a query (e.g., Axis("cell") |> LookupVector("age") |> Abs() ). For this there should be other constructor(s) tailored for this usage.

An element-wise operation may be applied to scalar, vector ot matrix data. It will preserve the shape of the data, but changes the value(s), and possibly the data type of the elements. For example, Abs will compute the absolute value of each value.

To implement a new such operation, the type is expected to be of the form:

struct MyOperation <: EltwiseOperation
    ... optional parameters ...
end
@query_operation MyOperation

MyOperation(operation_name::Token, parameter_values::Dict{String, Token})::MyOperation

The constructor should use parse_parameter for each of the parameters (for example, using parse_number_assignment ). In addition you will need to invoke @query_operation to register the operation so it can be used in a query, and implement the functions listed below. See the query operations module for details and examples.

DataAxesFormats.Registry.compute_eltwise Function
compute_eltwise(operation::EltwiseOperation, input::StorageMatrix)::StorageMatrix
compute_eltwise(operation::EltwiseOperation, input::StorageVector)::StorageVector
compute_eltwise(operation::EltwiseOperation, input_value::Number)::StorageReal

Compute an EltwiseOperation operation .

Reduction operations

DataAxesFormats.Registry.ReductionOperation Type

Abstract type for all reduction operations.

In a string query, this is specified using the %> operator (e.g., %> Sum , %> Quantile fraction 0.05 ):

ReductionOperation := %> operation ( parameter value )*

Since each ReductionOperation isa QueryOperation , you can directly apply it to a query (e.g., Axis("cell") |> Axis("gene") |> LookupMatrix("UMIs") |> Quantile(0.05) ). To allow for this, the reduction class should provide constructor(s) tailored for this usage.

A reduction operation may be applied to matrix or vector data. It will reduce (eliminate) one dimension of the data, and possibly the result will have a different data type than the input. When applied to a vector, the operation will return a scalar. When applied to a matrix, you must specify the axis that is to be eliminated from the result (as per Julia's conventions).

To implement a new such operation, the type is expected to be of the form:

struct MyOperation <: ReductionOperation
    ... optional parameters ...
end

MyOperation(operation_name::Token, parameter_values::Dict{String, Token})::MyOperation

The constructor should use parse_parameter for each of the parameters (for example, using typically parse_number_assignment ). In addition you will need to invoke @query_operation to register the operation so it can be used in a query, and implement the functions listed below. See the query operations module for details and examples.

DataAxesFormats.Registry.compute_reduction Function
compute_reduction(operation::ReductionOperation, input::StorageMatrix, axis::Integer)::StorageVector
compute_reduction(operation::ReductionOperation, input::StorageMatrix)::StorageVector
compute_reduction(operation::ReductionOperation, input::StorageVector)::StorageReal

Since each ReductionOperation isa QueryOperation , you can directly apply it to a query (e.g., Axis("cell") |> Axis("gene") |> LookupMatrix("UMIs") |> Sum() ). For this there should be other constructor(s) tailored for this usage.

When reducing a matrix, if an axis is specified, that axis is the one being eliminated. For example, axis = 1 (or Rows ) means the result will have one entry per column. If no axis is specified, the matrix is reduced to a scalar.

Note

Most reduction operations are wildly inefficient if the eliminated axis is not the Rows , that is, if the result doesn't have one value per column of the original matrix.

DataAxesFormats.Registry.reduction_result_type Function
reduction_result_type(operation::ReductionOperation, eltype::Type)::Type

Return the data type of the result of the reduction operation if applied to a vector of the specified eltype .

DataAxesFormats.Registry.supports_strings Function
supports_strings(operation::ComputationOperation)::Bool

Most operations do not support string operands. The very few that do are explicitly marked in the documentation.

Registering operations

DataAxesFormats.Registry.@query_operation Macro
struct MyOperation <: EltwiseOperation  # Or <: ReductionOperation
    ...
end
@query_operation MyOperation

Automatically call register_query_operation for MyOperation .

Note this will import DataAxesFormats.Registry.register_query_operation , so it may only be called from the top level scope of a module.

DataAxesFormats.Registry.register_query_operation Function
register_query_operation(
    type::Type{<:Union{EltwiseOperation, ReductionOperation}},
    source_file::AbstractString,
    source_line::Integer,
)::Nothing

Register a specific operation so it would be available inside queries. This is required to be able to parse the operation. This is idempotent (safe to invoke multiple times).

This isn't usually called directly. Instead, it is typically invoked by using the @query_operation macro.

Index