Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
7455f5c
#28 /8206 feat: TreeSummarizedExperiment
At6789Vi Aug 4, 2026
7642598
#28 /8222 feat(cellosaurus): like Biopython Bio.ExPASy.cellosaurus
At6789Vi Aug 4, 2026
7859606
#28 /8238 feat(ranged_summarized_experiment): RangedSummarizedExperim…
At6789Vi Aug 4, 2026
7c0a488
#28 /8261 feat(unigene): NCBI UniGene
At6789Vi Aug 4, 2026
8af1dc9
#28 /8299 feat: GRangesList unlist/relist && u RangedSummarizedExperi…
At6789Vi Aug 4, 2026
47c39c2
#28 /8332 feat(hhr): Bio.Align.hhr HHsearch/HHblits
At6789Vi Aug 4, 2026
6219fc8
#28 /8373 feat(sparse_array): Bioconductor SparseArray COO
At6789Vi Aug 4, 2026
49bdf34
#28 /8409 feat(cealign): Bio.PDB.cealign CEAligner CA/C4 AFP CE Z-sco…
At6789Vi Aug 4, 2026
c903057
#28 feat(scrapper): Bioconductor scrapper RNA-seq
At6789Vi Aug 4, 2026
fbe8b4a
#28 feat(binary_cif): Bio.PDB.binary_cif BinaryCIF maskPDB
At6789Vi Aug 4, 2026
3fba531
#28 feat(milo): Bioconductor miloR & KNN & GLM & graph spatial FDR
At6789Vi Aug 4, 2026
bfc10dc
#28 /8555 feat(infernal): Infernal cmscan/cmsearch Bio.SearchIO.Infer…
At6789Vi Aug 4, 2026
e66a1f6
#28 /8593 feat(variance_partition): LMM & ML/REML、BLUP、precision weig…
At6789Vi Aug 4, 2026
9d461a9
#28 /8634 feat(shared_reference_alignment): PWA/MSA insertion slots
At6789Vi Aug 4, 2026
cebe4c5
#28 feat(decontx): Bioconductor decontX k-means & SingleCellExperiment
At6789Vi Aug 4, 2026
34b6755
#28 /8721 feat(alignment_map): Bio.Align.Alignment map/mapall overhan…
At6789Vi Aug 4, 2026
8b48413
#28 feat(zinbwave): ZINB-WaVE
At6789Vi Aug 4, 2026
f522d3b
feat(bigbed): Bio.Align.bigbed & BigBed v4 & BED3-BED12 & AutoSQL & …
At6789Vi Aug 4, 2026
9cab648
#28 feat(apeglm): apeglm GLM & Cauchy/Student-t & Laplace & FSR/FSOS/…
At6789Vi Aug 4, 2026
1730ead
#28 feat(bigmaf): UCSC BigMaf
At6789Vi Aug 4, 2026
015a9e9
#28 feat(dreamlet): Bioconductor dreamlet sample×cell-type pseudobulk…
At6789Vi Aug 5, 2026
e8f330f
#28 feat(bigpsl): Biopython Bio.Align.bigpsl
At6789Vi Aug 5, 2026
a434c30
#28 /9196 feat(aldex2): Bioconductor ALDEx2
At6789Vi Aug 5, 2026
32ececb
#28 feat(alignment): Biopython Alignment.counts & BLOSUM45
At6789Vi Aug 5, 2026
acecd70
#28 feat: Bioconductor DirichletMultinomial DMM ROC SummarizedExperiment
At6789Vi Aug 5, 2026
1b8c1e7
#28 feat(align_tabular): Bio.Align.tabular & BLAST outfmt7 & FASTA 8C…
At6789Vi Aug 5, 2026
aca0823
#28 feat(nnsvg): Bioconductor nnSVG & kNN & NNGP & profile ML & Spati…
At6789Vi Aug 5, 2026
6829929
feat(align_psl): Bio.Align.psl UCSC PSL/PSLX
At6789Vi Aug 5, 2026
850f438
#28 feat(banksy): Bioconductor Banksy & banksy & lambda & PCA & k-mea…
At6789Vi Aug 5, 2026
6aa169e
328 feat(align_sam): Bio.Align.sam alignment-aware SAM implementation…
At6789Vi Aug 5, 2026
0ad274d
#28 feat(celda): Bioconductor celda_CG
At6789Vi Aug 5, 2026
464e4ec
#28 pass: 10046 feat: Bio.Align.a2m & Bio.Align.emboss EMBOSS & Bio.A…
At6789Vi Aug 5, 2026
8dce9b1
#28 pass:10852 feat: MSF, NEXUS, Stockholm, Chain, MAF, BED alignment…
At6789Vi Aug 5, 2026
263503f
#28 pass: 11572 feat: spicyr、bluster、flowsom、muscat、dropletUtils、mast…
At6789Vi Aug 6, 2026
8d650c9
#28 pass: 12093 feat: BLAST XML & CLUSTAL & PHYLIP & Mauve & PAML BAS…
At6789Vi Aug 6, 2026
69efe13
#38 pass: 12151 refactor: more format
At6789Vi Aug 6, 2026
77ef7ba
publish 0.1.7
At6789Vi Aug 6, 2026
67f1535
chore: v0.1.8
At6789Vi Aug 7, 2026
ce228c3
Merge branch 'main' of github.com:At6789Vi/BioSeqs
At6789Vi Aug 7, 2026
2262c9d
update
At6789Vi Aug 7, 2026
4d87250
#28 pass: 12183 feat: Nei-Gojobori & Z Test & Fisher & dN/dS & BH-FDR…
At6789Vi Aug 7, 2026
07c304f
#28 feat(protein_analysis): Chou-Fasman IUPred COILS Kolaskar-Tongaon…
At6789Vi Aug 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1,171 changes: 1,119 additions & 52 deletions README.md

Large diffs are not rendered by default.

77 changes: 77 additions & 0 deletions examples/a2m_demo/main.mbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
///|
fn main {
println("=== Biopython Bio.Align.a2m Demo ===")

let alignment = @src.a2m_parse(@src.a2m_example_text()) catch {
_ => abort("failed to parse A2M sample")
}

println("\n1. State-aware A2M parsing")
println(" " + alignment.summary())
println(" Column states: " + alignment.states)
println(" Reference sequence: " + alignment.sequences[0].sequence)

println("\n2. Insertion slots and match consensus")
for insertion in alignment.insertion_runs() {
println(
" Slot " +
insertion.slot.to_string() +
": columns [" +
insertion.start_column.to_string() +
", " +
insertion.end_column.to_string() +
"), width " +
insertion.width.to_string(),
)
}
let consensus = alignment.consensus(include_insertions=false) catch {
_ => abort("failed to calculate A2M consensus")
}
println(" Match-state consensus: " + consensus)

println("\n3. Coordinate mapping")
match alignment.map_position(0, 1, 5) {
Some(position) =>
println(
" Reference residue 5 maps to query_one residue " +
position.to_string() +
" (zero-based)",
)
None => println(" Reference residue 5 maps to a query_one gap")
}

println("\n4. Pairwise alignment statistics")
let counts = alignment.pair_counts(0, 1) catch {
_ => abort("failed to calculate A2M pair counts")
}
println(
" Aligned/identity/mismatch: " +
counts.aligned.to_string() +
"/" +
counts.identities.to_string() +
"/" +
counts.mismatches.to_string(),
)
println(" Identity fraction: " + counts.identity().to_string())

println("\n5. Match-only projection")
let projected = alignment.match_projection() catch {
_ => abort("failed to project A2M match columns")
}
println(" " + projected.summary())
println(" Projected states: " + projected.states)

println("\n6. Wrapped canonical serialization")
let serialized = @src.a2m_write(alignment, line_width=6) catch {
_ => abort("failed to write A2M alignment")
}
let reparsed = @src.a2m_parse(serialized) catch {
_ => abort("failed to reparse A2M alignment")
}
println(" Serialized bytes: " + serialized.length().to_string())
println(
" Round trip preserved alignment: " + (alignment == reparsed).to_string(),
)

println("\n=== Demo Complete ===")
}
5 changes: 5 additions & 0 deletions examples/a2m_demo/moon.pkg
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {
"IvanAXu/BioSeqs/src",
}

pkgtype(kind: "executable")
145 changes: 145 additions & 0 deletions examples/aldex2_demo/main.mbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
///|
fn print_feature(result : @src.Aldex2Result, name : String) -> Unit {
let effect = match result.effects.find_feature(name) {
Some(value) => value
None => abort("ALDEx2 example feature not found: " + name)
}
let tests = match result.tests.find_feature(name) {
Some(value) => value
None => abort("ALDEx2 example test result not found: " + name)
}
println(
" " +
name +
": effect=" +
effect.effect.to_string() +
", overlap=" +
effect.overlap.to_string() +
", Welch eBH=" +
tests.welch_adjusted.to_string() +
", Wilcoxon eBH=" +
tests.wilcoxon_adjusted.to_string(),
)
}

///|
fn main {
println("=== Bioconductor ALDEx2 Demo ===")
let (counts, conditions, features, samples) = @src.aldex2_example_data()
let config = @src.Aldex2Config::create(
mc_samples=64,
denominator=@src.Aldex2Iqlr,
seed=2026,
) catch {
_ => abort("failed to create ALDEx2 configuration")
}

println("\n1. Draw deterministic Dirichlet instances and apply IQLR")
let clr = @src.aldex2_clr(
counts,
conditions,
config~,
feature_names=features,
sample_names=samples,
) catch {
Aldex2Error(message) => abort("failed to construct ALDEx2 CLR: " + message)
}
println(
" retained features=" +
clr.feature_count().to_string() +
", removed all-zero features=" +
clr.removed_feature_count().to_string() +
", samples=" +
clr.sample_count().to_string() +
", Monte Carlo instances=" +
clr.mc_sample_count().to_string(),
)

println("\n2. Estimate posterior tests and standardized effects")
let result = @src.aldex2(
counts,
conditions,
config~,
feature_names=features,
sample_names=samples,
) catch {
Aldex2Error(message) => abort("failed to run ALDEx2: " + message)
}
print_feature(result, "increased")
print_feature(result, "decreased")
print_feature(result, "stable_high")
print_feature(result, "rare_increased")

println("\n3. Rank, select, and summarize compositional effects")
let ranked = result.ranked()
let summary = result.summary(maximum_adjusted=0.1, minimum_effect=1.0)
println(
" largest absolute effect=" +
ranked[0].feature_name +
" (" +
ranked[0].effect.to_string() +
")",
)
println(
" Welch eBH <= 0.10=" +
summary.significant_welch_count.to_string() +
", |effect| >= 1=" +
summary.large_effect_count.to_string() +
", jointly selected=" +
result.select(maximum_adjusted=0.1, minimum_effect=1.0).length().to_string(),
)

println("\n4. Compute posterior expected Aitchison distances")
let distances = result.clr.expected_distance()
println(
" distance(C1, T1)=" +
distances[0][4].to_string() +
", symmetric=" +
(distances[0][4] == distances[4][0]).to_string(),
)

println("\n5. Add posterior summaries to an immutable container copy")
let assays : Map[String, Array[Array[Double]]] = Map([("counts", counts)])
let metadata : Map[String, String] = Map([("source", "aldex2_demo")])
let experiment = @src.summarized_experiment(assays, [], [], metadata)
let output = @src.aldex2_summarized_experiment(
experiment,
conditions,
config~,
feature_names=features,
sample_names=samples,
) catch {
Aldex2Error(message) =>
abort("failed to integrate ALDEx2 with SummarizedExperiment: " + message)
}
let effect_assay = match @src.se_assay(output.experiment, "aldex2_effect") {
Some(value) => value
None => abort("ALDEx2 effect assay missing")
}
println(
" effect rows=" +
effect_assay.length().to_string() +
", source object unchanged=" +
(@src.se_assay(experiment, "aldex2_effect") is None).to_string(),
)

println("\n6. Export an ALDEx2-compatible tabular summary")
println(result.to_tsv())

println("7. Invalid count matrices produce explicit diagnostics")
let rejected = try {
ignore(
@src.aldex2([[2.0, -1.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]], [
"A", "A", "B", "B",
]),
)
false
} catch {
Aldex2Error(message) => {
println(" " + message)
true
}
}
println(" malformed counts rejected=" + rejected.to_string())
println("\n=== Demo Complete ===")
}
6 changes: 6 additions & 0 deletions examples/aldex2_demo/moon.pkg
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {
"IvanAXu/BioSeqs/src",
"moonbitlang/core/hashmap",
}

pkgtype(kind: "executable")
157 changes: 157 additions & 0 deletions examples/align_bed_demo/main.mbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
///|
fn bed_coordinate_path_text(
coordinates : Array[@src.AlignBedCoordinate],
) -> String {
let output = StringBuilder::new()
for index = 0; index < coordinates.length(); index = index + 1 {
if index > 0 {
output.write_string(" -> ")
}
output.write_string(
"(" +
coordinates[index].target.to_string() +
", " +
coordinates[index].query.to_string() +
")",
)
}
output.to_string()
}

///|
fn main {
println("=== Biopython Bio.Align.bed Demo ===")

let document = @src.align_bed_parse(@src.align_bed_example_text()) catch {
AlignBedError(message) => abort("BED parsing failed: " + message)
}
let plus = document.alignments[0]
let minus = document.alignments[1]

println("\n1. Parse mixed BED3 and BED12 records")
println(
" records=" +
document.alignments.length().to_string() +
", targets=" +
document.targets().length().to_string() +
", queries=" +
document.queries().length().to_string(),
)
println(
" numeric score=" +
plus.score.unwrap().number().unwrap_or(-1.0).to_string(),
)
let text_score_document = @src.align_bed_parse(
"chr1\t10\t20\tcurated-hit\thigh-confidence\t+",
) catch {
AlignBedError(message) => abort("text BED score parsing failed: " + message)
}
println(
" text score=" +
text_score_document.alignments[0].score.unwrap().text_value().unwrap_or(
"missing",
),
)

println("\n2. Inspect plus/minus target-query coordinate paths")
println(" plus: " + bed_coordinate_path_text(plus.coordinates))
println(" minus: " + bed_coordinate_path_text(minus.coordinates))
println(
" plus strand=" +
plus.strand() +
", minus strand=" +
minus.strand(),
)

println("\n3. Reconstruct exon blocks and transcript sizes")
for index = 0; index < plus.blocks().length(); index = index + 1 {
let block = plus.blocks()[index]
println(
" exon " +
(index + 1).to_string() +
": target[" +
block.target_start.to_string() +
", " +
block.target_end.to_string() +
") query[" +
block.query_start.to_string() +
", " +
block.query_end.to_string() +
")",
)
}
println(
" plus query size=" +
plus.query_size().to_string() +
", minus query size=" +
minus.query_size().to_string(),
)

println("\n4. Map aligned residues in both directions")
println(
" plus target 1000 -> query " +
plus.map_target_position(1000).unwrap_or(-1).to_string(),
)
println(
" plus query 1054 -> target " +
plus.map_query_position(1054).unwrap_or(-1).to_string(),
)
println(
" minus target 2000 -> query " +
minus.map_target_position(2000).unwrap_or(-1).to_string(),
)
println(
" intron target 3000 -> query " +
plus.map_target_position(3000).unwrap_or(-1).to_string(),
)

println("\n5. Count path operations and query half-open intervals")
let counts = plus.counts()
let summary = document.summary()
let hits = document.search("chr22", 4900, 5100) catch {
AlignBedError(message) => abort("BED interval search failed: " + message)
}
println(
" aligned=" +
counts.aligned.to_string() +
", intron bases=" +
counts.target_skip_bases.to_string() +
", blocks=" +
counts.blocks.to_string(),
)
println(
" document aligned=" +
summary.aligned_bases.to_string() +
", plus/minus=" +
summary.plus_strand_count.to_string() +
"/" +
summary.minus_strand_count.to_string(),
)
println(" chr22 overlaps [4900, 5100): " + hits.length().to_string())

println("\n6. Project one alignment to BED3 through BED12")
for columns = 3; columns <= 12; columns = columns + 1 {
let line = @src.align_bed_format(plus, bed_columns=columns) catch {
AlignBedError(message) => abort("BED formatting failed: " + message)
}
println(
" BED" +
columns.to_string() +
": " +
line[0:line.length() - 1].to_owned(),
)
}

println("\n7. Write canonical BED12 and parse it again")
let single = @src.AlignBedDocument::create([plus]) catch {
AlignBedError(message) => abort("BED document creation failed: " + message)
}
let canonical = @src.align_bed_write(single) catch {
AlignBedError(message) => abort("BED serialization failed: " + message)
}
let round_trip = @src.align_bed_parse(canonical) catch {
AlignBedError(message) => abort("BED round-trip parsing failed: " + message)
}
println(" " + canonical[0:canonical.length() - 1].to_owned())
println(" round-trip preserved: " + (round_trip == single).to_string())
}
Loading
Loading