Add bioinformatics, hexdump
| author |
Steve Losh <steve@stevelosh.com> |
| date |
Fri, 02 Oct 2026 11:39:24 -0400 |
| parents |
d05f5412e9aa
|
| children |
0711b20b976c
|
| branches/tags |
(none) |
| files |
losh.asd make-docs.lisp src/bioinformatics.lisp src/debugging.lisp src/package.lisp |
Changes
--- a/losh.asd Tue Nov 11 14:34:11 2025 -0500
+++ b/losh.asd Fri Oct 02 11:39:24 2026 -0400
@@ -30,6 +30,7 @@
(:file "base" :depends-on ("package"))
;; 0 ---------------------------------------------------------
+ (:file "bioinformatics" :depends-on ("base"))
(:file "chili-dogs" :depends-on ("base"))
(:file "clos" :depends-on ("base"))
(:file "eldritch-horrors" :depends-on ("base"))
@@ -75,6 +76,7 @@
"mutation"))
(:file "debugging" :depends-on ("control-flow"
"math"
+ "shell"
"hash-tables"))
;; 5 ---------------------------------------------------------
--- a/make-docs.lisp Tue Nov 11 14:34:11 2025 -0500
+++ b/make-docs.lisp Fri Oct 02 11:39:24 2026 -0400
@@ -3,9 +3,10 @@
(defparameter *document-packages*
(list "LOSH"
+ "LOSH.ARRAYS"
"LOSH.ASTAR"
- "LOSH.ARRAYS"
"LOSH.BASE"
+ "LOSH.BIOINFORMATICS"
"LOSH.BITS"
"LOSH.CHILI-DOGS"
"LOSH.CLOS"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/bioinformatics.lisp Fri Oct 02 11:39:24 2026 -0400
@@ -0,0 +1,88 @@
+(in-package :losh.bioinformatics)
+
+
+(defun nxx (data n key)
+ (if (alexandria:emptyp data)
+ 0
+ (let* ((lengths (sort (map 'vector key data) #'>))
+ (total (reduce #'+ lengths))
+ (target (* total n)))
+ (loop :with x = 0
+ :for l :across lengths
+ :do (incf x l)
+ :when (>= x target) :do (return l)))))
+
+(defun n50 (data &key (key #'identity))
+ "Return the N50 statistic of `data`.
+
+ `key` will be called on each element of `data` and should return the length
+ of each datum.
+
+ An empty `data` will return an N50 of `0`.
+
+ Examples:
+
+ (n50 (list 2 3 4 5 6 7 8 9 10))
+ ;; => 8
+
+ (n50 (vector \"ACTACCAT\"
+ \"CAGAC\"
+ \"GCTT\"
+ \"CCCCCCC\"
+ \"CCAACCAAA\"
+ \"CA\")
+ :key #'length)
+ ;; => 7
+
+ "
+ (nxx data 0.5d0 key))
+
+(defun n90 (data &key (key #'identity))
+ "Return the N90 statistic of `data`.
+
+ `key` will be called on each element of `data` and should return the length
+ of each datum.
+
+ An empty `data` will return an N90 of `0`.
+
+ Examples:
+
+ (n90 (list 2 3 4 5 6 7 8 9 10))
+ ;; => 4
+
+ (n90 (vector \"ACTACCAT\"
+ \"CAGAC\"
+ \"GCTT\"
+ \"CCCCCCC\"
+ \"CCAACCAAA\"
+ \"CA\")
+ :key #'length)
+ ;; => 4
+
+ "
+ (nxx data 0.9d0 key))
+
+
+(defparameter *x*
+ (list
+ 990 990 990
+ 2500
+ 10000 12000 12000 14000
+ )
+ )
+
+(defparameter *y*
+ (list
+ 23 10 99
+ 7938
+ 6000 6000 12000 21400
+ )
+ )
+
+(list
+ (float (alexandria:mean *x*))
+ (n50 *x*)
+ '--
+ (float (alexandria:mean *y*))
+ (n50 *y*)
+ )
--- a/src/debugging.lisp Tue Nov 11 14:34:11 2025 -0500
+++ b/src/debugging.lisp Fri Oct 02 11:39:24 2026 -0400
@@ -74,6 +74,11 @@
(format stream "~v,'0X" (/ size 4) n)
(values))
+(defun hexdump (bytes)
+ "Dump `bytes` to standard out by shelling out to `xeh`."
+ (write-string (sh (list "xeh") :input bytes :result-type 'string))
+ (values))
+
(defmacro shut-up (&body body)
"Run `body` with stdout and stderr redirected to the void."
`(let ((*standard-output* (make-broadcast-stream))
@@ -242,4 +247,3 @@
`(iterate (repeat ,n)
(collect (progn ,@body))))
-
--- a/src/package.lisp Tue Nov 11 14:34:11 2025 -0500
+++ b/src/package.lisp Fri Oct 02 11:39:24 2026 -0400
@@ -115,6 +115,13 @@
(:export
:with-eof-handled))
+(defpackage :losh.bioinformatics
+ (:use :cl :iterate :losh.base)
+ (:documentation "Utilities related to bioinformatics.")
+ (:export
+ :n50
+ :n90))
+
(defpackage :losh.io
(:use :cl :iterate :losh.base)
@@ -439,6 +446,7 @@
(defpackage :losh.debugging
(:use :cl :iterate :losh.base
:losh.math
+ :losh.shell
:losh.control-flow
:losh.hash-tables)
(:documentation "Utilities for figuring out what the hell is going on.")
@@ -454,6 +462,7 @@
:dis
:gimme
:hex
+ :hexdump
:phr
:pr
:pretty-print-hash-table
@@ -500,6 +509,7 @@
:losh.arrays
:losh.astar
:losh.base
+ :losh.bioinformatics
:losh.bits
:losh.chili-dogs
:losh.clos