Skip to content

Masked sequences #5

Description

@J-Wall

Thanks for sharing this crate with the community Jeff. It looks really clean!

I have some suggestions for additional codecs to support masked sequences. Of course, I can easily just implement these in my own application thanks to your Codec derive macro, but following the philosophy of this crate, it might make sense to just implement them once for if others want to use them.

Often, we deal with DNA sequences which can be soft-masked, represented by lowercase, e.g.

ACGTaaatACGT
    |--| <- soft-masked region

or hard-masked, represented by N/n. Sometimes both at the same time.
Therefore we have an alphabet of 10 characters;
A, C, G, T, N, a, c, g, t, and n.
2⁴ would cover that with 6 spare, so you could throw in gaps - and padding . characters:

use bio_seq::codec::Codec;
use bio_seq_derive::Codec;

#[derive(Clone, Copy, Debug, PartialEq, Codec)]
#[bits(4)]
#[repr(u8)]
pub enum MaskedDna {
    A = 0b0000,
    C = 0b0001,
    G = 0b0010,
    T = 0b0011,
    #[alt(0b1010, 0b1001)]
    N = 0b1000,
    #[display('a')]
    ASoftMasked = 0b0100,
    #[display('c')]
    CSoftMasked = 0b0101,
    #[display('g')]
    GSoftMasked = 0b0110,
    #[display('t')]
    TSoftMasked = 0b0111,
    #[display('n')]
    #[alt(0b1110, 0b1101)]
    NSoftMasked = 0b1100,
    #[display('-')]
    Gap = 0b1011,
    #[display('.')]
    Pad = 0b1111,
}

The obvious extension (and what I actually have a use-case for) is masked IUPAC sequences. Something like

#[derive(Clone, Copy, Debug, PartialEq, Codec)]
#[bits(5)]
#[repr(u8)]
pub enum MaskedIupac {
    A = 0b01000,
    C = 0b00100,
    G = 0b00010,
    T = 0b00001,
    R = 0b01010,
    Y = 0b00101,
    S = 0b00110,
    W = 0b01001,
    K = 0b00011,
    M = 0b01100,
    B = 0b00111,
    D = 0b01011,
    H = 0b01101,
    V = 0b01110,
    N = 0b01111,
    #[display('a')]
    ASoftMasked = 0b11000,
    #[display('c')]
    CSoftMasked = 0b10100,
    #[display('g')]
    GSoftMasked = 0b10010,
    #[display('t')]
    TSoftMasked = 0b10001,
    #[display('r')]
    RSoftMasked = 0b11010,
    #[display('y')]
    YSoftMasked = 0b10101,
    #[display('s')]
    SSoftMasked = 0b10110,
    #[display('w')]
    WSoftMasked = 0b11001,
    #[display('k')]
    KSoftMasked = 0b10011,
    #[display('m')]
    MSoftMasked = 0b11100,
    #[display('b')]
    BSoftMasked = 0b10111,
    #[display('d')]
    DSoftMasked = 0b11011,
    #[display('h')]
    HSoftMasked = 0b11101,
    #[display('v')]
    VSoftMasked = 0b11110,
    #[display('n')]
    NSoftMasked = 0b11111,
    #[display('-')]
    Gap = 0b00000,
    #[display('.')]
    Pad = 0b10000,
}

Finally, one could add 3-bit representations of HardMaskedDna (which allows N, and maybe -/. but not lowercase letters), and 3-bit SoftMaskedDna, which allows acgt, but not N or -/.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions