Setting up filters
Filters can be easily configured based on a filter table, making it easy to template sets of operations. Filters are NOT applied sequentially, but run independently. If you do want to run filters in sequentially, you will have to run successive iterations, but this is easy enough to do. An easy way to maintain filters and edit them is to store them in a google sheet and load them into R. Then using the function tglow_filters_from_table to create the filter objects. The filter table should have the columns described under Filter tables, and one sheet for feature level filters, and one for object level filters. The filtering is customizable using grep patterns, so you can specify which filter is applied to which features.
There are two flavors of filters:
filter_vec_x: Accepts a vector and returns a logical vector of the same length (i.e. 'which objects for this feature are > 0')filter_agg_x: Accepts a vector and aggregates on a statistic and returns a single logical (i.e 'is the variance of this feature > 0')
Then there are the filter modifiers
filter_vec_x_sum: Applies the filter to multiple columns, returning a logical of nrow(input), where T only if all columns for that row are T, otherwise Ffilter_agg_x_multicol: Applies a filter to data with multiple columns and returns a logical vector of ncol(input). To apply these at the object level (i.e. 'filter objects with >x% of NA features'), settranspose=Tin the filter definition.
Filters return TRUE for what should be kept. Feature filters (calculate_feature_filters()) are called on one feature at a time, so use the base filter_agg_x filters there. Object filters (calculate_object_filters()) always receive a matrix of the selected features, so use filter_vec_x_sum or filter_agg_x_multicol with transpose=T.
Filtering example
Filter objects where _mito features have more then 50% NA's and overall features objects have no more then 10% NA's. Another example can be found in /vingettes/example.r
The result is a logical matrix of objects x filters, where TRUE means the object passes. To keep only objects that pass all filters:
Defining custom filters
You can also define custom filters at runtime by loading a new function into the global environment. Just make sure it has the following signature function(vec, thresh, grouping=NULL). A feature filter receives one feature as a vector and should return a single logical.
An object filter receives a matrix of objects x selected features, plus grouping, and should return a logical per object. Use filter_sum() to apply a vector filter to each column and keep only objects that pass in all columns.
Filter tables
tglow_filters_from_table() picks the table columns by position. By default name is column 1, column_pattern column 2, func column 3 and threshold column 4. Set name.col, col.col, func.col and thresh.col if your layout differs. trans.col and active.col are optional. If they are not set, transpose defaults to FALSE and active to TRUE. Any other columns, such as notes, are ignored.
A filter definition has no grouping. Filters that respect grouping use the grouping= argument of calculate_object_filters(), a vector with one value per object (e.g. getDataByObject(tglow, "donor")).
Available filters
Feature: works in calculate_feature_filters(). Object: works in calculate_object_filters(). The base filter_agg_x filters also run as object filters, but return a single value that is applied to all objects.
filter_agg_zero_var should also be covered by filter_agg_coef_var.
filter_vec_mod_z_perc is called on a matrix of objects x features:
The filter tables in /vingettes/example.r were written for tglow_example. When reading data with read_cellprofiler_parquet(), the cell_Neighbors_* and cell_Children_nucl_Count columns are placed on @meta instead of the assay, so assay-based filters on them select no features and are skipped. Filter these with manual filters on @meta instead.
Using manual filters
It is also fully possible to manually filter things using slicing. For example to filter NA's for the cell x position on the @meta slot you can simply:
This will create a new dataset with the objects filtered out.
The same can work for features, but these are filtered on the assay level, as each assay can have different number of features