File: multifit.ml

package info (click to toggle)
ocamlgsl 0.3.5-3
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 3,444 kB
  • ctags: 2,901
  • sloc: ml: 7,956; ansic: 6,796; makefile: 303; sh: 87; awk: 13
file content (82 lines) | stat: -rw-r--r-- 2,159 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
let _ = 
  Gsl_error.init ()

let read_lines () =
  let acc = ref [] in
  let cnt = ref 0 in
  begin
    try
      while true do
	acc := (read_line ()) :: !acc ;
	incr cnt ;
    done;
    with End_of_file -> ()
  end ;
  Printf.printf "read %d points\n" !cnt ;
  List.rev !acc

exception Wrong_format
let parse_input =
  let lexer = Genlex.make_lexer [] in
  let parse_data = parser
    | [< 'Genlex.Float a; 'Genlex.Float b; 'Genlex.Float c >] -> (a, b, c) in
  fun line ->
    try
      parse_data (lexer (Stream.of_string line))
    with Stream.Failure | Stream.Error _ -> raise Wrong_format

let parse_data lines =
  let n = List.length lines in
  let x = Array.make n 0. in
  let y = Array.make n 0. in
  let w = Array.make n 0. in
  let _ = List.fold_left
      (fun i line ->
	let (xi, yi, ei) as p = parse_input line in
	Printf.printf "%3g %.5g +/- %g\n" xi yi ei ;
	x.(i) <- xi ;
	y.(i) <- yi ;
	w.(i) <- (1. /. (ei *. ei)) ;
	succ i) 0 lines in
  print_newline ();
  (x, y, w)

let setup (x, y, w) = 
  let n = Array.length x in
  let x' = Gsl_matrix.create n 3 in
  let y' = Gsl_vector.of_array y in
  let w' = Gsl_vector.of_array w in
  for i=0 to pred n do
    let xi = x.(i) in
    x'.{i, 0} <- 1.0 ;
    x'.{i, 1} <- xi ;
    x'.{i, 2} <- xi *. xi ;
  done ;
  (x', y', w')

let fit (x, y, w) = 
  let (c, cov, chisq) = Gsl_multifit.linear ~weight:(`V w) (`M x) (`V y) in
  Printf.printf "# best fit: Y = %g + %g X + %g X^2\n"
    c.{0} c.{1} c.{2} ;
  Printf.printf "# covariance matrix:\n" ;
  Printf.printf "[ %+.5e, %+.5e, %+.5e  \n"
    cov.{0,0} cov.{0,1} cov.{0,2} ;
  Printf.printf "  %+.5e, %+.5e, %+.5e  \n"
    cov.{1,0} cov.{1,1} cov.{1,2} ;
  Printf.printf "  %+.5e, %+.5e, %+.5e ]\n"
    cov.{2,0} cov.{2,1} cov.{2,2} ;
  Printf.printf "# chisq = %g\n" chisq

let fit_alt (x, y, w) =
  let (c, cov, chisq) = Gsl_multifit.fit_poly ~weight:w ~x ~y 3 in
  assert(Array.length c = 4) ;
  Printf.printf "# best fit: Y = %g + %g X + %g X^2 + %g X^3\n"
    c.(0) c.(1) c.(2) c.(3) ;
  Printf.printf "# chisq = %g\n" chisq
  

let _ = 
  let data = parse_data (read_lines ()) in
  fit (setup data) ;
  print_newline () ;
  fit_alt data ;