#!/bin/sh #-*-scheme-*- exec guile -s $0 "$@" !# ;; GCB 27jan06 ;; ;; grok the bruker acqu files ;; use extracted values to get referencing informations (use-modules (ice-9 rdelim) (ice-9 format) (srfi srfi-1)) ; ----- utilities ---- (define (enumerate-interval a b) (if (> a b) '() (cons a (enumerate-interval (+ 1 a) b)))) ; -------------------- (define infile-name "acqus") ; example regexp code: ; an example of a single parameter: ; ##$BF4= 600.03 (define rx:line-single (make-regexp "^##.([^ ]+)= (.*)$")) ;; an example of an array parameter: ;##$AMP= (0..31) ;100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 ;100 100 100 100 100 100 100 100 100 100 100 100 100 100 ; note: special characters e.g. ) must be backslash-escaped twice, once due ; to scheme string parsing and once due to regex parsing. (define rx:line-array (make-regexp "^##.([^ ]+)= \\([0-9]+\\.\\.[0-9]+\\)$")) (define (grab-lines) (with-input-from-file infile-name (lambda() (let ((rx:delim (make-regexp "^##\\$"))) (define (grab-one result line-list) (let ((line (read-line))) (if (eof-object? line) result (if (regexp-exec rx:delim line) (grab-one (append result (list line-list)) (list line)) (grab-one result (append line-list (list line))))))) (grab-one '() '()))))) (define (lines->list lines) (define (string-full? str) (> (string-length str) 0)) (filter string-full? (apply append (map (lambda (line) (string-split line #\ )) lines)))) (define (grok-lines lines) (map (lambda (line) (let ((first-line (car line))) (let ((match:array (regexp-exec rx:line-array first-line))) (if match:array (let ((name (string->symbol (match-get-elem match:array 1)))) (cons name (lines->list (cdr line)))) (let ((match:single (regexp-exec rx:line-single first-line))) (and match:single (cons (string->symbol (match-get-elem match:single 1)) (match-get-elem match:single 2)))))))) lines)) ; example of a regex match object: ; #(##$ZL4= 120 (0 . 11) (3 . 6) (8 . 11)) (define (match-get-elem match elem) (let ((index (+ elem 1))) (if (> index (vector-length match)) #f (let ((str (vector-ref match 0)) (limits (vector-ref match index))) (substring str (car limits)(cdr limits)))))) (define table (grok-lines (grab-lines))) (define (get-entry name . rest) (define (get-entry-n name n) (let ((entry (assoc name table))) (and entry (if (list? (cdr entry)) (list-ref (cdr entry) n) (cdr entry))))) (if (null? rest) (get-entry-n name 1) (get-entry-n name (car rest)))) (define (get-entry-numeric name . rest) (let ((result (apply get-entry name rest))) (if (string? result) (string->number result)))) ; ----- start referencing section ----- ;; from BMRB: relative frequencies for 0ppm standard nucleus (define get-relative-frequency (let ((freq-table '((H 1.000) (h 1.000) (H1 1.000) (N15 0.101329118) (N 0.101329118) (n 0.101329118) (C 0.251449530) (c 0.251449530) (C13 0.251449530)))) (lambda (nuc) (cond ((assoc nuc freq-table) => cadr) (else #f))))) (define (get-frequency-ratio nuc-1 nuc-2) (/ (get-relative-frequency nuc-1) (get-relative-frequency nuc-2))) ;; sf in MHz; (define (reference nuc-1 sf-1 ppm-1 nuc-2 sf-2) (let* ((hz-1 (* ppm-1 sf-1)) (sf0-1 (- (* 1e6 sf-1) hz-1)) (sf0-2 (* sf0-1 (get-frequency-ratio nuc-2 nuc-1))) (hz-2 (* sf-2 1e6)) (sigma-2 (/ (- hz-2 sf0-2) sf0-2)) (ppm-2 (* sigma-2 1e6))) ppm-2)) (define (verbose-reference nuc-1 sf-1 ppm-1 nuc-2 sf-2) (let ((hz-1 (* ppm-1 sf-1))) (format #t "nucleus 1 offset ~a ppm (= ~a hz)~%" ppm-1 hz-1) (let ((sf0-1 (- (* 1e6 sf-1) hz-1))) (format #t "zero frequency of nucleus 1 = ~a hz~%" sf0-1) (let* ((ratio (get-frequency-ratio nuc-2 nuc-1)) (sf0-2 (* sf0-1 ratio))) (format #t "zero frequency of nucleus 2 = ~a hz using ratio ~a~%" sf0-2 ratio) (let* ((hz-2 (* 1e6 sf-2)) (delta-hz-2 (- hz-2 sf0-2)) (ppm-2 (* 1e6 (/ delta-hz-2 sf0-2)))) (format #t "nuc 2 freq. = ~a (~a ppm)~%" delta-hz-2 ppm-2)))))) ; ------------------------------------- (define x-car (let ((cmd (command-line))) (if (> (length cmd) 1) (string->number (cadr cmd)) 4.80))) (define bf2 (reference 'h (get-entry-numeric 'SFO1) x-car 'c (get-entry-numeric 'BF2))) (define sfo2 (reference 'h (get-entry-numeric 'SFO1) x-car 'n (get-entry-numeric 'SFO2))) (define sfo3 (reference 'h (get-entry-numeric 'SFO1) x-car 'c (get-entry-numeric 'SFO3))) ;; freq report (format #t "~%#-- Bruker referencing report ; using xCAR=~a --~%" x-car) (format #t "# bf2=~a ppm ; sfo2=~a ppm ; sfo3=~a ppm~%~%" bf2 sfo2 sfo3) (write-line "# CNST array:") (display "# ") (for-each (lambda (n) (let ((cnst (get-entry 'CNST n))) (format #t "cnst~a=~a " n cnst)) 'ok) (enumerate-interval 1 24)) (newline)