Add open source force spectroscopy post.
authorW. Trevor King <wking@drexel.edu>
Sat, 23 Apr 2011 18:57:47 +0000 (14:57 -0400)
committerW. Trevor King <wking@drexel.edu>
Sat, 23 Apr 2011 18:57:47 +0000 (14:57 -0400)
posts/Open_source_force_spectroscopy.mdwn [new file with mode: 0644]
posts/Open_source_force_spectroscopy/0001-Added-math.h-include-to-fs_align_histogram2d.h.patch [new file with mode: 0644]
posts/Open_source_force_spectroscopy/0002-changed-abs-double-to-fabs-double-in-fs_fit_spectr.patch [new file with mode: 0644]
posts/Open_source_force_spectroscopy/0003-Updated-wxWindows-code-to-compile-on-wx-2.8.patch [new file with mode: 0644]
posts/Open_source_force_spectroscopy/0004-Added-wxglade-entry-to-Makefile-for-regenerating-aut.patch [new file with mode: 0644]
posts/Open_source_force_spectroscopy/fs_kit_tutorial.pdf [new file with mode: 0644]

diff --git a/posts/Open_source_force_spectroscopy.mdwn b/posts/Open_source_force_spectroscopy.mdwn
new file mode 100644 (file)
index 0000000..7987ea3
--- /dev/null
@@ -0,0 +1,116 @@
+There are a number of open source packages dealing with aspects of
+single-molecule force spectroscopy.  Here's a list of everything I've
+heard about to date.
+
+=============  ===========  ======================================================
+Package        License      Purpose
+=============  ===========  ======================================================
+[[calibcant]]  GPL v3+      Cantilever thermal calibration
+[fs_kit][]     GPL v2+      Force spectra analysis pattern recognition
+[Hooke][]      LGPL v3+     Force spectra analysis and unfolding force extraction
+[[sawsim]]     GPL v3+      Monte Carlo unfolding/refolding simulation and fitting
+[refolding][]  Apache v2.0  Double-pulse experiment control and analysis
+=============  ===========  ======================================================
+
+calibcant
+=========
+
+[[Calibcant]] is my [[Python]] module for AFM cantilever calibration
+via the thermal tune method.  It's based on [[Comedi]], so it needs
+work if you want to use it on a non-Linux system.  If you're running a
+Linux kernel, it should be pretty easy to get it running on your
+system.  Email me if there's any way I can help set it up for your
+lab.
+
+fs_kit
+======
+
+[fs_kit][] is a package for force spectra analysis pattern
+recognition.  It was developed by Michael Kuhn and Maurice Hubain at
+Daniel Müller's lab when they were at TU~Dresden
+([paper][fs_kit_paper]).  It has an [[Igor]] interface, but the bulk
+of the project is in [[C++]] with a [wxWidgets][] interface.  fs_kit
+is versioned in CVS at `bioinformatics.org`, and you can check out
+their code with:
+
+    $ cvs -d:pserver:anonymous@bioinformatics.org:/cvsroot checkout fskit
+
+The last commit was on 2005/05/16, so it's a bit crusty.  I patched
+things up back in 2008 so it would compile again,
+
+[[!inline pages="./Open_source_force_spectroscopy/*.patch" archive=yes quick=yes]]
+
+but when I emailed Michael with the patches I got this:
+
+    On Thu, Oct 23, 2008 at 11:21:42PM +0200, Michael Kuhn wrote:
+    > Hi Trevor,
+    >
+    > I'm glad you could fix fs-kit, the project is otherwise pretty dead,
+    > as was the link. I found an old file which should be the tutorial,
+    > hopefully in the latest version. The PDF is probably lost.
+    >
+    > bw, Michael
+
+So, it's a bit of a fixer-upper, but it was the first open source
+package in this field that I know of.  I've put up a [[PDF
+version|fs_kit_tutorial]] of the tutorial Michael sent me in case
+you're interested.
+
+Hooke
+=====
+
+[Hooke][] is a [[force spectroscopy]] data analysis package written in
+[[Python]].  It was initially developed by Massimo Sandal, Fabrizio
+Benedetti, Marco Brucale, Alberto Gomez-Casado while at Bruno Samorì's
+lab at U~Bologna ([paper][hooke_paper].  Suprisingly, there are
+commits by all of the authors except Samorì himself).  Hooke provides
+the interface between your raw data and theory.  It has a drivers for
+reading most force spectroscopy file formats, and a large number of
+commands for manipulating and analyzing the data.
+
+I liked Hooke so much I threw out my already-written package that had
+been performing a similar role and proceeded to work over Hooke to
+merge together the diverging command-line and GUI forks.
+Unfortunately, my fork has not yet been merged back in as the main
+branch, but I'm optimistic that it will eventually.  The homepage for
+my branch is [[here|Hooke]].
+
+sawsim
+======
+
+While programs like Hooke can extract unfolding forces from
+velocity-clamp experiments, the unfolding force histograms are
+generally compared to simulated data to estimate the underlying
+kinetic parameters.  [[Sawsim]] is my package for performing such
+simulations and fitting them to the experimental histograms
+([paper][sawsim_paper).  The single-pull simulator is written in
+[[C]], and there is a nice [[Python]] wrapper that manages the
+thousands of simulated pulls needed to explore the possible model
+parameter space.  The whole package ends up being pretty fast,
+flexible, and convenient.
+
+refolding
+=========
+
+[Refolding][refolding] is a suite for performing and analyzing
+double-pulse refolding experiments.  It was initially developed by
+Daniel Aioanei, also at the Samorí lab in Bologna (these guys are
+great!). The experiment-driver is mostly written in [[Java]] with the
+analysis code in [[Python]].  The driver is curious; it uses the
+NanoScope scripting interface to drive the experiment *through* the
+NanoScope software by impersonating a mouse-wielding user (like
+[Selenium][] does for web browsers).  See the `RobotNanoDriver.java`
+code for details.
+
+[fs_kit]: http://fskit.blogspot.com/
+[fs_kit_paper]: http://dx.doi.org/10.1111/j.1365-2818.2005.01478.x
+[wxWidgets]: http://www.wxwidgets.org/
+[Hooke]: http://code.google.com/p/hooke/
+[Hooke_paper]: http://dx.doi.org/10.1093/bioinformatics/btp180
+[sawsim_paper]: http://dx.doi.org/10.1016/j.ijbiomac.2009.12.001
+[refolding]: http://code.google.com/p/refolding/
+[refolding_paper]: http://dx.doi.org/10.1093/bioinformatics/btq663
+[Selenium]: http://seleniumhq.org/
+
+[[!tag tags/programming]]
+[[!tag tags/theory]]
diff --git a/posts/Open_source_force_spectroscopy/0001-Added-math.h-include-to-fs_align_histogram2d.h.patch b/posts/Open_source_force_spectroscopy/0001-Added-math.h-include-to-fs_align_histogram2d.h.patch
new file mode 100644 (file)
index 0000000..eeccd49
--- /dev/null
@@ -0,0 +1,31 @@
+From 67bdccaf0d328eae57142235dd66b1bdf2a1be66 Mon Sep 17 00:00:00 2001
+From: W. Trevor King <wking@drexel.edu>
+Date: Tue, 21 Oct 2008 09:36:29 -0400
+Subject: [PATCH] Added math.h include to fs_align_histogram2d.h.
+
+Do Mac/Windows compilers include math.h by default?
+I was getting:
+  /usr/bin/gcc -W -Wall -Wno-long-double -I/sw/include -Dfs_gui_wxwidgets -I/usr/lib/wx/include/gtk2-unicode-release-2.8 -I/usr/include/wx-2.8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES -D__WXGTK__
+  src/fs_align_aspectrum.cpp -c  -o fs_align_aspectrum.o
+  In file included from src/fs_align_aspectrum.h:5,
+                   from src/fs_align_aspectrum.cpp:1:
+  src/fs_align_histogram2d.h: In constructor `fs_align::fineHistogram2D::fineHistogram2D(size_t, size_t, double, double, double, double, double, double)':
+  src/fs_align_histogram2d.h:130: error: `ceil' was not declared in this scope
+with gcc 4.2.3 (Ubuntu 4.2.3-2ubuntu7)
+---
+ src/fs_align_histogram2d.h |    1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/src/fs_align_histogram2d.h b/src/fs_align_histogram2d.h
+index f29e37e..5cd8f39 100644
+--- a/src/fs_align_histogram2d.h
++++ b/src/fs_align_histogram2d.h
+@@ -1,4 +1,5 @@
++#include <math.h>
+ #include <gsl/gsl_histogram2d.h>
+ #include <gsl/gsl_sf_erf.h>
+ #include <gsl/gsl_vector.h>
+-- 
+1.5.4.3
+
diff --git a/posts/Open_source_force_spectroscopy/0002-changed-abs-double-to-fabs-double-in-fs_fit_spectr.patch b/posts/Open_source_force_spectroscopy/0002-changed-abs-double-to-fabs-double-in-fs_fit_spectr.patch
new file mode 100644 (file)
index 0000000..75275ed
--- /dev/null
@@ -0,0 +1,45 @@
+From 81f8a53d2c0ec948f9396fc58be0328b502392c4 Mon Sep 17 00:00:00 2001
+From: W. Trevor King <wking@drexel.edu>
+Date: Tue, 21 Oct 2008 10:28:29 -0400
+Subject: [PATCH] changed abs(double) to fabs(double) in fs_fit_spectrum.cpp
+
+Also added math.h include to fs_select_tree.cpp
+---
+ src/fs_fit_spectrum.cpp |    4 ++--
+ src/fs_select_tree.cpp  |    1 +
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/src/fs_fit_spectrum.cpp b/src/fs_fit_spectrum.cpp
+index 6c04d7b..1e295b8 100644
+--- a/src/fs_fit_spectrum.cpp
++++ b/src/fs_fit_spectrum.cpp
+@@ -572,7 +572,7 @@ void fs_fit::Spectrum::adjustZeroTSS() throw (fs_fitFitException)
+         if (tss > high_tss)
+             throw fs_fitFitException("contact point not found","cp_not_found");            
+         
+-        if (abs(force) < range)
++        if (fabs(force) < range)
+         {
+             if (!first) { first = true; first_idx = i; }
+             n++;
+@@ -597,7 +597,7 @@ void fs_fit::Spectrum::adjustZeroTSS() throw (fs_fitFitException)
+         const double tss = gsl_vector_get(data->rawtss, i);
+         const double force = gsl_vector_get(data->rawforce, i) - data->bl_a - data->bl_b * tss;
+     
+-        if (abs(force) < range)
++        if (fabs(force) < range)
+             sd += sqr(tss - shift);
+         
+         i++;
+diff --git a/src/fs_select_tree.cpp b/src/fs_select_tree.cpp
+index fff072d..407cf5e 100644
+--- a/src/fs_select_tree.cpp
++++ b/src/fs_select_tree.cpp
+@@ -1,3 +1,4 @@
++#include <math.h>
+ #include "fs_select_tree.h"
+ void fs_select::Tree::loadTree(string filename)
+-- 
+1.5.4.3
+
diff --git a/posts/Open_source_force_spectroscopy/0003-Updated-wxWindows-code-to-compile-on-wx-2.8.patch b/posts/Open_source_force_spectroscopy/0003-Updated-wxWindows-code-to-compile-on-wx-2.8.patch
new file mode 100644 (file)
index 0000000..0d5c7a7
--- /dev/null
@@ -0,0 +1,1269 @@
+From 9c4d46b8007f85fa4d7c6c285c1c64a766d4001e Mon Sep 17 00:00:00 2001
+From: W. Trevor King <wking@drexel.edu>
+Date: Tue, 21 Oct 2008 19:53:51 -0400
+Subject: [PATCH] Updated wxWindows code to compile on wx-2.8.
+
+Most of the difficulties were caused by wxString no longer being
+interchangable with c strings and stdlib strings.  I also cleaned
+up the logging code a bit.
+---
+ src/fs_align_aspectrum.cpp       |   19 ++--
+ src/fs_align_aspectrumvector.cpp |   15 +--
+ src/fs_align_clusterdriver.cpp   |   24 +++---
+ src/fs_fit_fitfrontend.cpp       |   18 ++--
+ src/fs_fit_model.cpp             |   26 +++---
+ src/fs_fit_spectrum.cpp          |   73 ++++++++------
+ src/fs_gui.wxg                   |   16 ++--
+ src/fs_gui_app.cpp               |    3 +-
+ src/fs_gui_layout.cpp            |  204 ++++++++++++++++++++------------------
+ src/fs_gui_layout.h              |   14 ++-
+ src/fs_kit_driver.cpp            |   73 +++++++++-----
+ src/fs_kit_options.cpp           |    6 +-
+ src/fs_kit_options.h             |   10 +--
+ 13 files changed, 272 insertions(+), 229 deletions(-)
+
+diff --git a/src/fs_align_aspectrum.cpp b/src/fs_align_aspectrum.cpp
+index 1528449..22f04e0 100644
+--- a/src/fs_align_aspectrum.cpp
++++ b/src/fs_align_aspectrum.cpp
+@@ -64,7 +64,8 @@ bool fs_align::ASpectrumFile::loadDataFromStream(string path, istream& list_inpu
+     if (list_filename.empty() || peaks.empty()) return false;
+-    if (options.logLevel >= 4) { ostringstream log; log << "loading file " << path << filename << endl; *options.stdOut << log.str().c_str(); }
++    if (options.logLevel >= 4)
++      *options.stdOut << "loading file " << path << filename << endl;
+     // load data into matrix
+     FILE* f = fopen( (path + filename).c_str(), "r");
+@@ -131,7 +132,8 @@ bool fs_align::ASpectrumFile::loadDataFromStream(string path, istream& list_inpu
+     string s, t;
+     double max_tss;
+     info_input >> s >> t >> min_tss >> max_tss;
+-    if (options.logLevel >= 4) { ostringstream log; log << "reading peak info " << s << endl; *options.stdOut << log.str().c_str(); }
++    if (options.logLevel >= 4)
++      *options.stdOut << "reading peak info " << s << endl;
+     info_input >> s;
+     while (s != "end") { info_input >> t >> max_tss >> s; }
+       
+@@ -215,7 +217,8 @@ bool fs_align::ASpectrumFile::loadPeaksFromStream(istream& fit_input)
+         fit_input >> filename >> xname >> status;
+     }
+-    if (options.logLevel >= 2) { ostringstream log; log << "reading peaks " << filename << endl; *options.stdOut << log.str().c_str(); }
++    if (options.logLevel >= 2)
++      *options.stdOut << "reading peaks " << filename << endl;
+     // store baseline data
+     fit_input >> bl_sd >> bl_mintss >> bl_mintss_sd >> bl_a >> bl_a_sd >> bl_b >> bl_b_sd;
+@@ -340,12 +343,10 @@ fs_align::SpectrumDistance* fs_align::ASpectrum::overlaySpectrum(ASpectrum& s)
+     }
+     if (options.logLevel >= 5)
+-    {
+-        ostringstream log; log << "overlap: " << getName() <<  " and " << s.getName() << 
+-        ": score " << maxscore / sqrt(1.0*nx*s.nx) << ", shift " << 
+-        options.alignPointDistance * maxshift + min_tss - s.min_tss << endl; 
+-        *options.stdOut << log.str().c_str(); 
+-    }
++      *options.stdOut << "overlap: " << getName() <<  " and " << s.getName()
++                     << ": score " << maxscore / sqrt(1.0*nx*s.nx) 
++                     << ", shift " << options.alignPointDistance * maxshift + min_tss - s.min_tss
++                     << endl; 
+     
+     SpectrumDistance* dist = new SpectrumDistance(this, &s, maxscore / sqrt(1.0*(nx*s.nx)), options.alignPointDistance * maxshift + min_tss - s.min_tss);
+     
+diff --git a/src/fs_align_aspectrumvector.cpp b/src/fs_align_aspectrumvector.cpp
+index 887f350..7f2ff3a 100644
+--- a/src/fs_align_aspectrumvector.cpp
++++ b/src/fs_align_aspectrumvector.cpp
+@@ -13,21 +13,18 @@ fs_align::ASpectrumVector::ASpectrumVector(Options& options)
+     ifstream fit_input(fit_filename.c_str());
+     ifstream info_input(info_filename.c_str());
+    
+-    if (!list_input) 
+-    {
+-        ostringstream log; log << "ERROR: Could not find file " << list_filename << endl; *options.stdOut << log.str().c_str();
++    if (!list_input) {
++      *options.stdOut << "ERROR: Could not find file " << list_filename << endl;
+         return;
+     }
+-    if (!fit_input) 
+-    {
+-        ostringstream log; log << "ERROR: Could not find file " << info_filename << endl; *options.stdOut << log.str().c_str();
++    if (!fit_input) {
++      *options.stdOut << "ERROR: Could not find file " << info_filename << endl;
+         return;
+     }
+-    if (!info_input) 
+-    {
+-        ostringstream log; log << "ERROR: Could not find file " << fit_filename << endl; *options.stdOut << log.str().c_str();
++    if (!info_input) {
++      *options.stdOut << "ERROR: Could not find file " << fit_filename << endl;
+         return;
+     }
+       
+diff --git a/src/fs_align_clusterdriver.cpp b/src/fs_align_clusterdriver.cpp
+index 170edfa..48c323a 100644
+--- a/src/fs_align_clusterdriver.cpp
++++ b/src/fs_align_clusterdriver.cpp
+@@ -14,9 +14,7 @@ void fs_align::ClusterDriver::doClustering()
+     const int n_dist = ssv.size() * (ssv.size() - 1) / 2;
+     if (options.logLevel >= 1)
+-    {
+-        { ostringstream log; log << "computing " << n_dist << " pairwise distances" << endl; *options.stdOut << log.str().c_str(); }
+-    }
++      *options.stdOut << "computing " << n_dist << " pairwise distances" << endl;
+     time_t start_time = time(0);
+     bool first = true;
+@@ -38,15 +36,13 @@ void fs_align::ClusterDriver::doClustering()
+             double dt = difftime(time(0), start_time);
+             const int f = (ssv.size() - 1);
+             
+-            { ostringstream log; log << "calculated " << f << " distances in " << dt << " seconds" << endl; *options.stdOut << log.str().c_str(); }
+-            { ostringstream log; log << "est. remaining time for distance calculation: " << dt * n_dist / f << " seconds" << endl; *options.stdOut << log.str().c_str(); }
++          *options.stdOut << "calculated " << f << " distances in " << dt << " seconds" << endl;
++          *options.stdOut << "est. remaining time for distance calculation: " << dt * n_dist / f << " seconds" << endl;
+         }
+     }
+     if (options.logLevel >= 1)
+-    {
+-        { ostringstream log; log << "distances have been calculated; clustering..." << endl; *options.stdOut << log.str().c_str(); }
+-    }
++      *options.stdOut << "distances have been calculated; clustering..." << endl;
+     dlist.sort(cmpSpectrumDistancePtr());
+@@ -62,7 +58,8 @@ void fs_align::ClusterDriver::doClustering()
+         ASpectrumCluster *nc = new ASpectrumCluster(lowest, options);
+         ssv.push_back(nc);
+         
+-        if (options.logLevel >= 4) { ostringstream log; log << "best overlap: " << lowest->oa->getName() << "\t" << lowest->ob->getName() << endl; *options.stdOut << log.str().c_str(); }
++        if (options.logLevel >= 4)
++        *options.stdOut << "best overlap: " << lowest->oa->getName() << "\t" << lowest->ob->getName() << endl;
+         
+         *tree << nc->getNumber() << " " << -lowest->score << endl;
+         
+@@ -132,7 +129,8 @@ void fs_align::ClusterDriver::alignSpectra()
+     
+     shift /= n;
+     
+-    if (options.logLevel >= 4) { ostringstream log; log << "shifting spectra by " << shift << " to center alignment" << endl; *options.stdOut << log.str().c_str(); }
++    if (options.logLevel >= 4)
++      *options.stdOut << "shifting spectra by " << shift << " to center alignment" << endl;
+     
+     // add average alignment shift to all spectra
+     // in result, average alignment shift is zero
+@@ -142,11 +140,13 @@ void fs_align::ClusterDriver::alignSpectra()
+         // as soon as we encounter a cluster, break loop
+         if (s->isCluster()) break;
+-        if (options.logLevel >= 4) { ostringstream log; log << s->getShift(); *options.stdOut << log.str().c_str(); }
++        if (options.logLevel >= 4)
++        *options.stdOut << s->getShift();
+         s->setShift(s->getShift() - shift);
+-        if (options.logLevel >= 4) { ostringstream log; log << "\t" << s->getShift() << endl; *options.stdOut << log.str().c_str(); }
++        if (options.logLevel >= 4)
++        *options.stdOut << "\t" << s->getShift() << endl;
+     }
+ }
+diff --git a/src/fs_fit_fitfrontend.cpp b/src/fs_fit_fitfrontend.cpp
+index b7a0db6..8931ebc 100644
+--- a/src/fs_fit_fitfrontend.cpp
++++ b/src/fs_fit_fitfrontend.cpp
+@@ -76,9 +76,11 @@ void fs_fit::FitFrontend::printHeader(ostream *o) {
+     Model *m = 0;
+     // model selection
+-    if (options.model == "wlc") m = new wlcModel(max_peaks, options); else
+-    if (options.model == "wlc_p") m = new wlcModel_p(max_peaks, options); else 
+-    ; // model not found but oh well
++    if (options.model == "wlc")
++      m = new wlcModel(max_peaks, options);
++    else if (options.model == "wlc_p")
++      m = new wlcModel_p(max_peaks, options);
++    // else // model not found but oh well
+     m->streamHeader(o);
+@@ -156,7 +158,7 @@ void fs_fit::FitFrontend::processSpectrum(string path, string filename, string x
+     
+         *temp_output << "end" << endl;
+     
+-        { ostringstream log; log << "ERROR: " << filename << " -- " << e.getError() << endl; *options.stdOut << log.str().c_str(); }
++      *options.stdOut << "ERROR: " << filename << " -- " << e.getError() << endl;
+     }
+     string result = temp_output->str();
+@@ -190,7 +192,9 @@ void fs_fit::FitFrontend::processFit() try {
+         count++;
+     }
+     
+-    if (options.logLevel >= 1) { ostringstream log; log << "processed " << count << " spectra" << endl; *options.stdOut << log.str().c_str(); }
++    if (options.logLevel >= 1) {
++      *options.stdOut << "processed " << count << " spectra" << endl;
++    }
+     printHeader(output_fitting);
+     for (list<string>::iterator it = output_buffer.begin(); it != output_buffer.end(); it++)
+@@ -202,9 +206,9 @@ void fs_fit::FitFrontend::processFit() try {
+         
+ }
+ catch (fs_fitInitException& e) {
+-    { ostringstream log; log << "ERROR: An error occured during initialization. No spectra are processed:" << endl << e.getError() << endl;   *options.stdOut << log.str().c_str(); }
++  *options.stdOut << "ERROR: An error occured during initialization. No spectra are processed:" << endl << e.getError() << endl;
+ }
+ catch (fs_fitException& e) {
+-    { ostringstream log; log << "ERROR: " << e.getError() << endl;   *options.stdOut << log.str().c_str(); }
++  *options.stdOut << "ERROR: " << e.getError() << endl;
+ }
+diff --git a/src/fs_fit_model.cpp b/src/fs_fit_model.cpp
+index 1461c08..2d56f3d 100644
+--- a/src/fs_fit_model.cpp
++++ b/src/fs_fit_model.cpp
+@@ -156,16 +156,12 @@ void fs_fit::Model::printSolverState(int iter, gsl_multifit_fdfsolver *solver)
+ {
+     if (options.logLevel < 3) return;
+     
+-    { ostringstream log; log << "it: " << setw(3) << iter << " fit: "; *options.stdOut << log.str().c_str(); }
++    *options.stdOut << "it: " << setw(3) << iter << " fit: ";
+     
+     for (size_t i = 0; i < getFitParams(); i++)
+-    {
+-        { ostringstream log; log << setw(8) << gsl_vector_get(solver->x, i); *options.stdOut << log.str().c_str(); }
+-    }
+-    
+-    { ostringstream log; log << " |f(x)| = " << setw(8) << gsl_blas_dnrm2 (solver->f); *options.stdOut << log.str().c_str(); }
++      *options.stdOut << setw(8) << gsl_vector_get(solver->x, i);
+     
+-    { ostringstream log; log << endl; *options.stdOut << log.str().c_str(); }
++    *options.stdOut << " |f(x)| = " << setw(8) << gsl_blas_dnrm2 (solver->f) << endl;
+ }
+@@ -183,8 +179,8 @@ void fs_fit::Model::printFunction(gsl_multifit_fdfsolver *solver)
+     {
+         for (int pos = it->getStart(); pos < it->getEnd(); pos++)
+         {
+-            { ostringstream log; log << setw(10) << gsl_vector_get(data->tss, pos) << "\t" << setw(10) << gsl_vector_get(data->force, pos) << setw(10) << "\t" << gsl_vector_get(solver->f, xpos) + gsl_vector_get(data->force, pos) << endl; *options.stdOut << log.str().c_str(); }
+-            xpos++;
++        *options.stdOut << setw(10) << gsl_vector_get(data->tss, pos) << "\t" << setw(10) << gsl_vector_get(data->force, pos) << setw(10) << "\t" << gsl_vector_get(solver->f, xpos) + gsl_vector_get(data->force, pos) << endl;
++        xpos++;
+         }
+         mpos++;
+     }    
+@@ -266,7 +262,8 @@ string fs_fit::Model::fitData(const double merge_threshold) throw(fs_fitExceptio
+                       throw fs_fitFitException(s.str(),"sc_no_peaks");
+               }
+-              if (delete_last > 0 && options.logLevel >= 3) { ostringstream log; log << "deleting last " << delete_last << "peak(s) with high countour length..." << endl; *options.stdOut << log.str().c_str(); }
++              if (delete_last > 0 && options.logLevel >= 3)
++                *options.stdOut << "deleting last " << delete_last << "peak(s) with high countour length..." << endl;
+         // check if peaks are too close to each other, if so, they will be merged
+         // (peaks will be merged pairwise)
+@@ -275,7 +272,8 @@ string fs_fit::Model::fitData(const double merge_threshold) throw(fs_fitExceptio
+         for (size_t i = getCommonParams(); i < getFitParams() - (delete_last + 1) * getPeakParams(); i += getPeakParams())
+             if (gsl_vector_get(solver->x,i+getPeakParams()) - gsl_vector_get(solver->x,i) < merge_threshold) { merge_peaks++; i += getPeakParams(); }
+         
+-        if (options.logLevel >= 3) { ostringstream log; log << "merging " << merge_peaks << " peaks..." << endl; *options.stdOut << log.str().c_str(); }
++        if (options.logLevel >= 3)
++        *options.stdOut << "merging " << merge_peaks << " peaks..." << endl;
+               
+         if (merge_peaks > 0 || delete_last > 0)
+         {
+@@ -342,7 +340,8 @@ string fs_fit::Model::fitData(const double merge_threshold) throw(fs_fitExceptio
+         {
+             // no peaks to merge, therefore: finish fitting
+         
+-            if (options.logLevel >= 3) { ostringstream log; log << gsl_strerror(status) << endl; *options.stdOut << log.str().c_str(); }
++            if (options.logLevel >= 3)
++            *options.stdOut << gsl_strerror(status) << endl;
+         
+             // determine covariance matrix, assign parameters and parameter standard deviation 
+             gsl_matrix *covar = gsl_matrix_alloc(getFitParams(), getFitParams());
+@@ -356,7 +355,8 @@ string fs_fit::Model::fitData(const double merge_threshold) throw(fs_fitExceptio
+             for (size_t i=0; i<getFitParams(); i++)
+             {
+                 gsl_vector_set(params_sd, i, sqrt(gsl_matrix_get(covar, i, i)));
+-                if (options.logLevel >= 3) { ostringstream log; log << setw(10) << gsl_vector_get(solver->x, i) << setw(10) << gsl_vector_get(params_sd, i) << endl; *options.stdOut << log.str().c_str(); }
++                if (options.logLevel >= 3)
++                *options.stdOut << setw(10) << gsl_vector_get(solver->x, i) << setw(10) << gsl_vector_get(params_sd, i) << endl;
+             }
+         
+             printFunction(solver);   
+diff --git a/src/fs_fit_spectrum.cpp b/src/fs_fit_spectrum.cpp
+index 1e295b8..8cffd5e 100644
+--- a/src/fs_fit_spectrum.cpp
++++ b/src/fs_fit_spectrum.cpp
+@@ -75,7 +75,8 @@ void fs_fit::Spectrum::loadFromASCIIFile(string path, string filename, int datap
+ {
+     if (datapoints != -1) this->datapoints = datapoints;
+-    if (options.logLevel >= 2) { ostringstream log; log << "loading file " << path << filename << endl; *options.stdOut << log.str().c_str(); }
++    if (options.logLevel >= 2)
++      *options.stdOut << "loading file " << path << filename << endl;
+     rawpoints = getNumberOfFields(filename);
+@@ -142,7 +143,8 @@ void fs_fit::Spectrum::loadFromASCIIFile(string path, string filename, int datap
+     // cout << filename << "\t" << datapoints << "\t" << data->force << endl; 
+-    if (options.logLevel >= 3) { ostringstream log; log << rawpoints << " points have been read, tss moved by " << -data->bl_mintss << endl; *options.stdOut << log.str().c_str(); }
++    if (options.logLevel >= 3)
++      *options.stdOut << rawpoints << " points have been read, tss moved by " << -data->bl_mintss << endl;
+ }
+ void fs_fit::Spectrum::reducePoints(double min_tss, double max_tss)
+@@ -206,7 +208,8 @@ void fs_fit::Spectrum::reducePoints(double min_tss, double max_tss)
+         // cout << t_avg << "\t" << f_avg << "\t" << sqrt(sd / (n_smooth - 1)) << endl;
+     }
+       
+-    if (options.logLevel >= 3) { ostringstream log; log << rawpoints << " points have been reduced to " << points << " points"<< endl; *options.stdOut << log.str().c_str(); }
++    if (options.logLevel >= 3)
++      *options.stdOut << rawpoints << " points have been reduced to " << points << " points"<< endl;
+ }
+ double fs_fit::Spectrum::fractionBaseline(double fraction)
+@@ -229,11 +232,11 @@ double fs_fit::Spectrum::fractionBaseline(double fraction)
+     data->bl_asd = sqrt(cov00);
+     data->bl_bsd = sqrt(cov11);
+     
+-    if (options.logLevel >= 3) { ostringstream log; log << "baseline fit: " << setw(5) << fraction  
+-        << " [" << gsl_vector_get(data->tss,start) << ", " << gsl_vector_get(data->tss,points-1) << "] "
+-        << " -- y = " << data->bl_a << " + x * " << data->bl_b << 
+-        " -- sd = " << data->bl_sd << endl;   
+-        *options.stdOut << log.str().c_str(); }
++    if (options.logLevel >= 3)
++      *options.stdOut << "baseline fit: " << setw(5) << fraction  
++                     << " [" << gsl_vector_get(data->tss,start) << ", " << gsl_vector_get(data->tss,points-1) << "] "
++                     << " -- y = " << data->bl_a << " + x * " << data->bl_b
++                     << " -- sd = " << data->bl_sd << endl;   
+         
+     return data->bl_sd;
+ }
+@@ -256,12 +259,14 @@ double fs_fit::Spectrum::fullSpectrumSD()
+     double bl_sd = sqrt(chisq/(n-1));
+     
+-    if (options.logLevel >= 3) { ostringstream log; log << "baseline fit to all points: " 
+-        << setw(5) << data->bl_fraction
+-        << " [" << gsl_vector_get(data->rawtss,start) << ", " << gsl_vector_get(data->rawtss,rawpoints-1) << "] "
+-        << " -- y = " << bl_a << " + x * " << bl_b << 
+-        " -- sd = " << bl_sd << endl;   
+-        *options.stdOut << log.str().c_str(); }
++    if (options.logLevel >= 3)
++      *options.stdOut << "baseline fit to all points: " 
++                     << setw(5) << data->bl_fraction
++                     << " [" << gsl_vector_get(data->rawtss,start)
++                     << ", " << gsl_vector_get(data->rawtss,rawpoints-1)
++                     << "] "
++                     << " -- y = " << bl_a << " + x * " << bl_b
++                     << " -- sd = " << bl_sd << endl;   
+         
+     data->full_sd = bl_sd;
+@@ -303,7 +308,8 @@ double fs_fit::Spectrum::iterativeBaseline(const double guess, const double incr
+       // check if baseline is too long
+     if (errorNotAttached()) { throw fs_fitFitException("no attachment","no_attachment"); }
+     if (warnNotAttached()) { 
+-        if (options.logLevel >= 2) { ostringstream log; log << "WARNING: over 50% of the spectrum are baseline" << endl;    *options.stdOut << log.str().c_str(); }
++        if (options.logLevel >= 2)
++        *options.stdOut << "WARNING: over 50% of the spectrum are baseline" << endl;
+     }
+     return sd;
+@@ -380,12 +386,12 @@ void fs_fit::Spectrum::refineBaseline(const double mintss)
+       /*data->bl_asd = sqrt(cov00);
+         data->bl_bsd = sqrt(cov11);
+         */
+-        if (options.logLevel >= 3) { ostringstream log; log << "refining baseline: " << setw(5) << fitpoints << " -- y = " << p_a << " + x * " << p_b <<  
++        if (options.logLevel >= 3) {
++        *options.stdOut << "refining baseline: " << setw(5) << fitpoints << " -- y = " << p_a << " + x * " << p_b <<  
+             " -- sd = " << p_sd << endl;   
+-            *options.stdOut << log.str().c_str(); }
+-        if (options.logLevel >= 3) { ostringstream log; log << "             best: " << setw(5) << min_pts << " -- y = " << min_a << " + x * " << min_b <<  
++        *options.stdOut << "             best: " << setw(5) << min_pts << " -- y = " << min_a << " + x * " << min_b <<  
+             " -- sd = " << min_sd << endl;   
+-            *options.stdOut << log.str().c_str(); }
++      }
+         gsl_vector_free(extbl_x);
+         gsl_vector_free(extbl_y);
+@@ -404,7 +410,8 @@ void fs_fit::Spectrum::subtractBaseline()
+         data->rawforce->data[i] -= data->bl_a + data->bl_b * data->rawtss->data[j];
+     }
+-    if (options.logLevel >= 3) { ostringstream log; log << "baseline subtracted: y = " << data->bl_a << " + x * " << data->bl_b << endl;    *options.stdOut << log.str().c_str(); }
++    if (options.logLevel >= 3)
++      *options.stdOut << "baseline subtracted: y = " << data->bl_a << " + x * " << data->bl_b << endl;
+ }
+ int fs_fit::Spectrum::initChunks(double sd_factor, double minforce, double mintss)
+@@ -416,9 +423,9 @@ int fs_fit::Spectrum::initChunks(double sd_factor, double minforce, double mints
+     // init number of condensed points -- is incremented by createChunk
+     data->fit_points = 0;
+-    if (options.logLevel >= 3) { ostringstream log; log << "dividing spectrum in chunks, peak threshold: " << threshold <<  
+-        " pN, minimal peak force " << minforce << " pN, minimal tip-sample separation: " << mintss << " nm. "  << endl;   
+-        *options.stdOut << log.str().c_str(); }
++    if (options.logLevel >= 3)
++      *options.stdOut << "dividing spectrum in chunks, peak threshold: " << threshold <<  
++      " pN, minimal peak force " << minforce << " pN, minimal tip-sample separation: " << mintss << " nm. "  << endl;
+     // skip non-specific interactions -- start scanning mintss nm after smallest tss
+     size_t start = 1;
+@@ -545,12 +552,14 @@ void fs_fit::Spectrum::createChunk(int start, int end, double minforce, double m
+     data->chunks.push_back(c);
+     data->fit_points += c.getPoints();
+     
+-    if (options.logLevel >= 3) { ostringstream log; log << "new chunk " << c.getFirst() << " -- " << c.getLast() << endl;        *options.stdOut << log.str().c_str(); }
++    if (options.logLevel >= 3)
++      *options.stdOut << "new chunk " << c.getFirst() << " -- " << c.getLast() << endl;
+ }
+ void fs_fit::Spectrum::adjustZeroTSS() throw (fs_fitFitException)
+ {
+-    if (options.logLevel >= 3) { ostringstream log; log << "Detecting contact point." << endl; *options.stdOut << log.str().c_str(); }
++    if (options.logLevel >= 3)
++      *options.stdOut << "Detecting contact point." << endl;
+     const double max_force = 2 * data->full_sd;
+     const double range = 1 * data->full_sd;
+@@ -609,17 +618,17 @@ void fs_fit::Spectrum::adjustZeroTSS() throw (fs_fitFitException)
+     data->bl_mintss += shift;
+     data->bl_mintss_sd = sd;
+     
+-    if (options.logLevel >= 3) { ostringstream log; log << "shifted by " << shift << " nm" << endl; *options.stdOut << log.str().c_str(); }
++    if (options.logLevel >= 3)
++      *options.stdOut << "shifted by " << shift << " nm" << endl;
+     
+     gsl_vector_add_constant(data->rawtss, -shift);
+ }
+ void fs_fit::Spectrum::streamDataPoints(ostream* o)
+ {
+-   for (size_t i = 0; i < points; i++)
+-        { ostringstream log; log << gsl_vector_get(data->tss, i) 
+-            << "\t" << gsl_vector_get(data->force, i)
+-            << "\t" << gsl_vector_get(data->force_sd, i) 
+-            << "\t" << gsl_vector_get(data->weight, i) << endl;
+-             *options.stdOut << log.str().c_str(); }
++  for (size_t i = 0; i < points; i++)
++    *options.stdOut << gsl_vector_get(data->tss, i) 
++                   << "\t" << gsl_vector_get(data->force, i)
++                   << "\t" << gsl_vector_get(data->force_sd, i) 
++                   << "\t" << gsl_vector_get(data->weight, i) << endl;
+ }
+diff --git a/src/fs_gui.wxg b/src/fs_gui.wxg
+index a8e6b17..4252552 100644
+--- a/src/fs_gui.wxg
++++ b/src/fs_gui.wxg
+@@ -1,7 +1,7 @@
+ <?xml version="1.0"?>
+-<!-- generated by wxGlade 0.3.1 on Mon Mar 22 12:06:10 2004 -->
++<!-- generated by wxGlade 0.6.3 on Tue Oct 21 14:05:03 2008 -->
+-<application path="D:\Micha\!afm\fskit\src\fs_gui_layout.h" name="" class="" option="0" language="C++" top_window="frame" encoding="ISO-8859-1" use_gettext="0" overwrite="0">
++<application path="fs_gui_layout.h" name="" class="" option="0" language="C++" top_window="frame" encoding="ISO-8859-1" use_gettext="0" overwrite="0" use_new_namespace="0" for_version="2.8" is_template="0">
+     <object class="guiFrame" name="frame" base="EditFrame">
+         <style>wxDEFAULT_FRAME_STYLE</style>
+         <title>fs_kit</title>
+@@ -99,10 +99,10 @@
+                                             <border>0</border>
+                                             <option>0</option>
+                                             <object class="wxButton" name="SettingsLoad" base="EditButton">
+-                                                <tooltip>Load settings file</tooltip>
+                                                 <label>Load...</label>
+-                                                <focused>1</focused>
++                                                <tooltip>Load settings file</tooltip>
+                                                 <id>ID_SET_OPEN</id>
++                                                <focused>1</focused>
+                                             </object>
+                                         </object>
+                                         <object class="sizeritem">
+@@ -184,8 +184,8 @@
+                                             <border>0</border>
+                                             <option>0</option>
+                                             <object class="wxButton" name="SpectraLoad" base="EditButton">
+-                                                <tooltip>Load list of spectra filenames</tooltip>
+                                                 <label>Load...</label>
++                                                <tooltip>Load list of spectra filenames</tooltip>
+                                                 <id>ID_SPEC_OPEN</id>
+                                             </object>
+                                         </object>
+@@ -281,8 +281,8 @@
+                                                             <border>0</border>
+                                                             <option>0</option>
+                                                             <object class="wxButton" name="SelectDir" base="EditButton">
+-                                                                <tooltip>Pick output directory</tooltip>
+                                                                 <label>Select...</label>
++                                                                <tooltip>Pick output directory</tooltip>
+                                                                 <id>ID_SELECT_DIR</id>
+                                                             </object>
+                                                         </object>
+@@ -441,10 +441,10 @@
+                                                             <border>0</border>
+                                                             <option>0</option>
+                                                             <object class="wxSpinCtrl" name="LogLevelCtrl" base="EditSpinCtrl">
+-                                                                <style>wxSP_ARROW_KEYS</style>
++                                                                <style>wxSP_ARROW_KEYS|wxTE_AUTO_URL</style>
++                                                                <id>ID_LOGLEVEL</id>
+                                                                 <range>-1, 5</range>
+                                                                 <value>0</value>
+-                                                                <id>ID_LOGLEVEL</id>
+                                                                 <size>40, -1</size>
+                                                             </object>
+                                                         </object>
+diff --git a/src/fs_gui_app.cpp b/src/fs_gui_app.cpp
+index b085cce..b83ebc6 100644
+--- a/src/fs_gui_app.cpp
++++ b/src/fs_gui_app.cpp
+@@ -27,8 +27,7 @@
+ bool BasicApplication::OnInit()
+ {
+   guiFrame *frame
+-    = new guiFrame
+-       (0, -1, "fs_gui");
++    = new guiFrame(0, -1, wxString("fs_gui", wxConvUTF8));
+   frame->Show(TRUE);
+   SetTopWindow(frame);
+diff --git a/src/fs_gui_layout.cpp b/src/fs_gui_layout.cpp
+index 3d928b7..a9dca2a 100644
+--- a/src/fs_gui_layout.cpp
++++ b/src/fs_gui_layout.cpp
+@@ -1,4 +1,4 @@
+-// -*- C++ -*- generated by wxGlade 0.3.1 on Sat Feb 14 18:44:55 2004
++// -*- C++ -*- generated by wxGlade 0.6.3 on Tue Oct 21 13:38:33 2008
+ // DO NOT EDIT BETWEEN "begin wxGlade" AND "end wxGlade"
+ /* fs_kit
+@@ -19,9 +19,10 @@
+  * along with this program; if not, write to the Free Software
+  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+  */ 
+- 
++
+ #ifdef fs_gui_wxwidgets
+  
++#include "fs_kit_options.h"
+ #include "fs_gui_layout.h"
+ enum { 
+@@ -54,61 +55,66 @@ BEGIN_EVENT_TABLE(guiFrame, wxFrame)
+   EVT_SPINCTRL  (ID_LOGLEVEL, guiFrame::OnLogLevel)
+ END_EVENT_TABLE()
++// begin wxGlade: ::extracode
++// end wxGlade
++
++
++
+ guiFrame::guiFrame(wxWindow* parent, int id, const wxString& title, const wxPoint& pos, const wxSize& size, long style):
+     wxFrame(parent, id, title, pos, size, wxDEFAULT_FRAME_STYLE)
+ {
+     // begin wxGlade: guiFrame::guiFrame
+-    notebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize, 0);
+-    notebook_pane_2 = new wxPanel(notebook, -1);
+-    notebook_log = new wxPanel(notebook, -1);
+-    borderpanel = new wxPanel(this, -1);
+-    middlepanel = new wxPanel(this, -1);
+-    toppanel = new wxPanel(this, -1);
++    notebook = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0);
++    notebook_pane_2 = new wxPanel(notebook, wxID_ANY);
++    notebook_log = new wxPanel(notebook, wxID_ANY);
++    borderpanel = new wxPanel(this, wxID_ANY);
++    middlepanel = new wxPanel(this, wxID_ANY);
++    toppanel = new wxPanel(this, wxID_ANY);
+     frame_menubar = new wxMenuBar();
+-    SetMenuBar(frame_menubar);
+     wxMenu* menu_file = new wxMenu();
+-    menu_file->Append(wxNewId(), wxT("&Open settings"), wxT(""), wxITEM_NORMAL);
++    menu_file->Append(wxNewId(), wxT("&Open settings"), wxEmptyString, wxITEM_NORMAL);
+     menu_file->Append(ID_EXIT, wxT("E&xit"), wxT("Exit fs_gui"), wxITEM_NORMAL);
+     frame_menubar->Append(menu_file, wxT("File"));
+-    frame_statusbar = CreateStatusBar(1);
+-    lblSettings = new wxStaticText(toppanel, -1, wxT("Settings:"));
++    SetMenuBar(frame_menubar);
++    frame_statusbar = CreateStatusBar(1, 0);
++    lblSettings = new wxStaticText(toppanel, wxID_ANY, wxT("Settings:"));
+     const wxString SettingsCombo_choices[] = {
+-        wxT("")
++        wxT("choice 1")
+     };
+-    SettingsCombo = new wxComboBox(toppanel, -1, "", wxDefaultPosition, wxDefaultSize, 1, SettingsCombo_choices, wxCB_DROPDOWN);
++    SettingsCombo = new wxComboBox(toppanel, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 1, SettingsCombo_choices, wxCB_DROPDOWN);
+     SettingsLoad = new wxButton(toppanel, ID_SET_OPEN, wxT("Load..."));
+     SettingsSave = new wxButton(toppanel, ID_SET_SAVE , wxT("Save..."));
+     SettingsSaveAs = new wxButton(toppanel, ID_SET_SAVEAS, wxT("Save As..."));
+-    lblSpectra = new wxStaticText(toppanel, -1, wxT("Spectra:"));
++    lblSpectra = new wxStaticText(toppanel, wxID_ANY, wxT("Spectra:"));
+     const wxString SpectraCombo_choices[] = {
+-        wxT("")
++        wxT("choice 1")
+     };
+-    SpectraCombo = new wxComboBox(toppanel, -1, "", wxDefaultPosition, wxDefaultSize, 1, SpectraCombo_choices, wxCB_DROPDOWN);
++    SpectraCombo = new wxComboBox(toppanel, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 1, SpectraCombo_choices, wxCB_DROPDOWN);
+     SpectraLoad = new wxButton(toppanel, ID_SPEC_OPEN, wxT("Load..."));
+-    SpectraSave = new wxButton(toppanel, -1, wxT("Save..."));
+-    SpectraSaveAs = new wxButton(toppanel, -1, wxT("Save As..."));
+-    lblDirectory = new wxStaticText(toppanel, -1, wxT("Output directory:"));
++    SpectraSave = new wxButton(toppanel, wxID_ANY, wxT("Save..."));
++    SpectraSaveAs = new wxButton(toppanel, wxID_ANY, wxT("Save As..."));
++    lblDirectory = new wxStaticText(toppanel, wxID_ANY, wxT("Output directory:"));
+     const wxString OutputDirectoryCombo_choices[] = {
+-        wxT("")
++        wxT("choice 1")
+     };
+-    OutputDirectoryCombo = new wxComboBox(toppanel, -1, "", wxDefaultPosition, wxDefaultSize, 1, OutputDirectoryCombo_choices, wxCB_DROPDOWN);
++    OutputDirectoryCombo = new wxComboBox(toppanel, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 1, OutputDirectoryCombo_choices, wxCB_DROPDOWN);
+     SelectDir = new wxButton(toppanel, ID_SELECT_DIR, wxT("Select..."));
+-    lblExpName = new wxStaticText(toppanel, -1, wxT("Experiment name:"));
++    lblExpName = new wxStaticText(toppanel, wxID_ANY, wxT("Experiment name:"));
+     const wxString ExperimentNameCombo_choices[] = {
+-        wxT("")
++        wxT("choice 1")
+     };
+-    ExperimentNameCombo = new wxComboBox(toppanel, -1, "", wxDefaultPosition, wxDefaultSize, 1, ExperimentNameCombo_choices, wxCB_DROPDOWN);
+-    radioProcessSpectra = new wxRadioButton(toppanel, -1, wxT("Process Spectra:"));
+-    chkFit = new wxCheckBox(toppanel, -1, wxT("Fit spectra"));
+-    chkAlign = new wxCheckBox(toppanel, -1, wxT("Align spectra"));
+-    chkSelect = new wxCheckBox(toppanel, -1, wxT("Select spectra"));
+-    chkClassify = new wxCheckBox(toppanel, -1, wxT("Classify peaks"));
+-    lblLogLevel = new wxStaticText(toppanel, -1, wxT("Log activty (-1 to 2 recommended):"));
+-    LogLevelCtrl = new wxSpinCtrl(toppanel, ID_LOGLEVEL, "0", wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, -1, 5);
+-    LogLevelLbl = new wxStaticText(toppanel, -1, wxT("LogLevelLbl"));
++    ExperimentNameCombo = new wxComboBox(toppanel, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 1, ExperimentNameCombo_choices, wxCB_DROPDOWN);
++    radioProcessSpectra = new wxRadioButton(toppanel, wxID_ANY, wxT("Process Spectra:"));
++    chkFit = new wxCheckBox(toppanel, wxID_ANY, wxT("Fit spectra"));
++    chkAlign = new wxCheckBox(toppanel, wxID_ANY, wxT("Align spectra"));
++    chkSelect = new wxCheckBox(toppanel, wxID_ANY, wxT("Select spectra"));
++    chkClassify = new wxCheckBox(toppanel, wxID_ANY, wxT("Classify peaks"));
++    lblLogLevel = new wxStaticText(toppanel, wxID_ANY, wxT("Log activty (-1 to 2 recommended):"));
++    LogLevelCtrl = new wxSpinCtrl(toppanel, ID_LOGLEVEL, wxT("0"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxTE_AUTO_URL, -1, 5);
++    LogLevelLbl = new wxStaticText(toppanel, wxID_ANY, wxT("LogLevelLbl"));
+     Start = new wxButton(middlepanel, ID_START, wxT("Start"));
+-    LogTextCtrl = new wxTextCtrl(notebook_log, ID_LOG_TEXTCTRL, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY);
+-    label_1 = new wxStaticText(notebook_pane_2, -1, wxT("Currently, the following features are not implemented:\n\n- providing a history of previously selected settings, file names, etc\n- validating manual (keyboard) input \n"));
++    LogTextCtrl = new wxTextCtrl(notebook_log, ID_LOG_TEXTCTRL, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY);
++    label_1 = new wxStaticText(notebook_pane_2, wxID_ANY, wxT("Currently, the following features are not implemented:\n\n- providing a history of previously selected settings, file names, etc\n- validating manual (keyboard) input \n"));
+     set_properties();
+     do_layout();
+@@ -120,8 +126,8 @@ guiFrame::guiFrame(wxWindow* parent, int id, const wxString& title, const wxPoin
+     SpectraCombo->Clear();
+     SettingsCombo->Clear();
+     OutputDirectoryCombo->Clear();
+-    
+-    wrapper = 0;    
++
++    wrapper = 0;
+ }
+@@ -138,26 +144,26 @@ void guiFrame::set_properties()
+     for(int i = 0; i < frame_statusbar->GetFieldsCount(); ++i) {
+         frame_statusbar->SetStatusText(frame_statusbar_fields[i], i);
+     }
+-    SettingsCombo->SetSize(wxSize(200, -1));
++    SettingsCombo->SetMinSize(wxSize(200, -1));
+     SettingsCombo->SetToolTip(wxT("Select settings file"));
+     SettingsCombo->SetSelection(0);
+     SettingsLoad->SetToolTip(wxT("Load settings file"));
+     SettingsLoad->SetFocus();
+-    SpectraCombo->SetSize(wxSize(200, -1));
++    SpectraCombo->SetMinSize(wxSize(200, -1));
+     SpectraCombo->SetToolTip(wxT("Select list of spectra filenames"));
+     SpectraCombo->SetSelection(0);
+     SpectraLoad->SetToolTip(wxT("Load list of spectra filenames"));
+     SpectraSave->Enable(false);
+     SpectraSaveAs->Enable(false);
+-    OutputDirectoryCombo->SetSize(wxSize(200, -1));
++    OutputDirectoryCombo->SetMinSize(wxSize(200, -1));
+     OutputDirectoryCombo->SetToolTip(wxT("Select output directory (empty: directory of settings file)"));
+     OutputDirectoryCombo->SetSelection(0);
+     SelectDir->SetToolTip(wxT("Pick output directory"));
+-    ExperimentNameCombo->SetSize(wxSize(200, -1));
++    ExperimentNameCombo->SetMinSize(wxSize(200, -1));
+     ExperimentNameCombo->SetToolTip(wxT("Enter or select experiment name"));
+     ExperimentNameCombo->SetSelection(0);
+     radioProcessSpectra->SetValue(1);
+-    LogLevelCtrl->SetSize(wxSize(40, -1));
++    LogLevelCtrl->SetMinSize(wxSize(40, -1));
+     Start->SetDefault();
+     // end wxGlade
+@@ -240,45 +246,30 @@ void guiFrame::do_layout()
+     topsizer->Add(20, 10, 0, 0, 0);
+     spacesizer->Add(topsizer, 0, wxEXPAND, 0);
+     spacesizer->Add(5, 20, 0, 0, 0);
+-    toppanel->SetAutoLayout(true);
+     toppanel->SetSizer(spacesizer);
+-    spacesizer->Fit(toppanel);
+-    spacesizer->SetSizeHints(toppanel);
+     mainsizer->Add(toppanel, 0, wxEXPAND, 0);
+     middlesizer->Add(5, 20, 0, 0, 0);
+     middlesizer->Add(Start, 0, 0, 0);
+-    middlepanel->SetAutoLayout(true);
+     middlepanel->SetSizer(middlesizer);
+-    middlesizer->Fit(middlepanel);
+-    middlesizer->SetSizeHints(middlepanel);
+     mainsizer->Add(middlepanel, 0, wxEXPAND, 0);
+     bordersizer->Add(20, 10, 0, 0, 0);
+-    borderpanel->SetAutoLayout(true);
+     borderpanel->SetSizer(bordersizer);
+-    bordersizer->Fit(borderpanel);
+-    bordersizer->SetSizeHints(borderpanel);
+     mainsizer->Add(borderpanel, 0, wxEXPAND, 0);
+     sizer_1->Add(LogTextCtrl, 1, wxALL|wxEXPAND, 0);
+-    notebook_log->SetAutoLayout(true);
+     notebook_log->SetSizer(sizer_1);
+-    sizer_1->Fit(notebook_log);
+-    sizer_1->SetSizeHints(notebook_log);
+     sizer_8->Add(label_1, 0, 0, 0);
+-    notebook_pane_2->SetAutoLayout(true);
+     notebook_pane_2->SetSizer(sizer_8);
+-    sizer_8->Fit(notebook_pane_2);
+-    sizer_8->SetSizeHints(notebook_pane_2);
+     notebook->AddPage(notebook_log, wxT("Log"));
+     notebook->AddPage(notebook_pane_2, wxT("Read Me"));
+-    mainsizer->Add(new wxNotebookSizer(notebook), 1, wxALL|wxEXPAND, 0);
+-    SetAutoLayout(true);
++    mainsizer->Add(notebook, 1, wxALL|wxEXPAND, 0);
+     SetSizer(mainsizer);
+     mainsizer->Fit(this);
+-    mainsizer->SetSizeHints(this);
+     Layout();
+     // end wxGlade
+ }
++
++
+ void guiFrame::OnLogFull(wxCommandEvent& event)
+ {
+     LogTextCtrl->Clear();
+@@ -286,7 +277,7 @@ void guiFrame::OnLogFull(wxCommandEvent& event)
+ wxString guiFrame::DescribeLogLevel(int level)
+ {
+-    wxString s;
++    string s;
+     switch (level)
+     {
+@@ -329,7 +320,7 @@ wxString guiFrame::DescribeLogLevel(int level)
+     
+     if (level > 3) s += " NOTE: Only use this when you process very few files. It's slow!";
+-    return s;
++    return wxString(s.c_str(), wxConvUTF8);
+ }
+ void guiFrame::OnLogLevel(wxSpinEvent& event)
+@@ -351,14 +342,18 @@ void guiFrame::OnMenu(wxCommandEvent& event)
+       // load settings file
+       case ID_SET_OPEN:
+       {
+-         wxFileDialog *fd = new wxFileDialog(this, "Choose a settings file", 
+-             "", "", "INI Files (*.ini)|*.ini|All files (*.*)|*.*", wxOPEN);
++         wxFileDialog *fd = new wxFileDialog(this,
++                                           wxString("Choose a settings file", wxConvUTF8),
++                                           wxString("", wxConvUTF8),
++                                           wxString("", wxConvUTF8),
++                                           wxString("INI Files (*.ini)|*.ini|All files (*.*)|*.*", wxConvUTF8),
++                                           wxOPEN);
+              
+          if (fd->ShowModal() == wxID_OK)
+          {
+             SettingsCombo->SetValue(fd->GetPath());
+             readOptions();
+-            LogTextCtrl->AppendText("Loaded settings file: " + fd->GetPath() + "\n");
++            LogTextCtrl->AppendText(wxString("Loaded settings file: ", wxConvUTF8) + fd->GetPath() + wxString("\n", wxConvUTF8));
+          }
+          
+          delete fd;
+@@ -367,9 +362,13 @@ void guiFrame::OnMenu(wxCommandEvent& event)
+       // display save as dialog and fall through to actual saving
+       case ID_SET_SAVEAS:
+       {
+-         wxFileDialog *fd = new wxFileDialog(this, "Save settings file as", 
+-             "", "", "INI Files (*.ini)|*.ini|All files (*.*)|*.*", wxSAVE | wxOVERWRITE_PROMPT);
+-             
++         wxFileDialog *fd = new wxFileDialog(this,
++                                           wxString("Save settings file as", wxConvUTF8),
++                                           wxString("", wxConvUTF8),
++                                           wxString("", wxConvUTF8),
++                                           wxString("INI Files (*.ini)|*.ini|All files (*.*)|*.*", wxConvUTF8),
++                                           wxSAVE | wxOVERWRITE_PROMPT);
++       
+          bool fall_through = false;
+          if (fd->ShowModal() == wxID_OK)
+          {
+@@ -384,10 +383,14 @@ void guiFrame::OnMenu(wxCommandEvent& event)
+       // save settings (fall through from above!)
+       case ID_SET_SAVE:
+       {
+-         if (SettingsCombo->GetValue() == "") {
+-    
+-             wxFileDialog *fd = new wxFileDialog(this, "Save settings file as", 
+-                 "", "", "INI Files (*.ini)|*.ini|All files (*.*)|*.*", wxSAVE | wxOVERWRITE_PROMPT);
++          if (SettingsCombo->GetValue() == wxString("", wxConvUTF8)) {
++         
++           wxFileDialog *fd = new wxFileDialog(this,
++                                           wxString("Save settings file as", wxConvUTF8),
++                                           wxString("", wxConvUTF8),
++                                           wxString("", wxConvUTF8),
++                                           wxString("INI Files (*.ini)|*.ini|All files (*.*)|*.*", wxConvUTF8),
++                                           wxSAVE | wxOVERWRITE_PROMPT);
+                  
+              if (fd->ShowModal() == wxID_OK)
+                 SettingsCombo->SetValue(fd->GetPath());
+@@ -395,27 +398,31 @@ void guiFrame::OnMenu(wxCommandEvent& event)
+              delete fd;
+          }
+          
+-         if (SettingsCombo->GetValue() == "") break;
++         if (SettingsCombo->GetValue() == wxString("", wxConvUTF8)) break;
+-         ofstream out(SettingsCombo->GetValue());
+-               
+-               if (out) {
+-                      Options *options = new Options(encodeOptions(), LogTextCtrl);
+-                      options->printOptions(&out);
+-               }
++       ofstream out(SettingsCombo->GetValue().mb_str());
++       if (out) {
++             Options *options = new Options(encodeOptions(), LogTextCtrl);
++             options->printOptions(&out);
++       }
++       
+          break;
+       }
+       // load spectrum file
+       case ID_SPEC_OPEN:
+       {
+-         wxFileDialog *fd = new wxFileDialog(this, "Choose a settings file", 
+-             "", "", "Filenames list (filenames.txt)|filenames.txt|Text files (*.txt)|*.txt|All files (*.*)|*.*", wxOPEN);
++         wxFileDialog *fd = new wxFileDialog(this,
++                                           wxString("Choose a settings file", wxConvUTF8),
++                                           wxString("", wxConvUTF8),
++                                           wxString("", wxConvUTF8),
++                                           wxString("INI Files (*.ini)|*.ini|All files (*.*)|*.*", wxConvUTF8),
++                                           wxOPEN);
+              
+          if (fd->ShowModal() == wxID_OK)
+          {
+             SpectraCombo->SetValue(fd->GetPath());
+-            LogTextCtrl->AppendText("Loaded filenames list: " + fd->GetPath() + "\n");
++            LogTextCtrl->AppendText(wxString("Loaded filenames list: ", wxConvUTF8) + fd->GetPath() + wxString("\n", wxConvUTF8));
+          }
+          
+          delete fd;
+@@ -424,12 +431,15 @@ void guiFrame::OnMenu(wxCommandEvent& event)
+       // select output directory
+       case ID_SELECT_DIR:
+       {
+-         wxDirDialog *dd = new wxDirDialog(this, "Choose an output directory", "", wxDD_NEW_DIR_BUTTON);
++         wxDirDialog *dd = new wxDirDialog(this,
++                                         wxString("Choose an output directory", wxConvUTF8),
++                                         wxString("", wxConvUTF8),
++                                         wxDD_NEW_DIR_BUTTON);
+              
+          if (dd->ShowModal() == wxID_OK)
+          {
+             OutputDirectoryCombo->SetValue(dd->GetPath());
+-            LogTextCtrl->AppendText("Selected output directory: " + dd->GetPath() + "\n");
++            LogTextCtrl->AppendText(wxString("Selected output directory: ", wxConvUTF8) + dd->GetPath() + wxString("\n", wxConvUTF8));
+          }
+          
+          delete dd;
+@@ -440,15 +450,15 @@ void guiFrame::OnMenu(wxCommandEvent& event)
+       {
+          if (!wrapper)
+          {
+-              Start->SetLabel("Stop");
++              Start->SetLabel(wxString("Stop", wxConvUTF8));
+               toppanel->Disable();
+-              LogTextCtrl->AppendText("Started fs_kit computation\n");
++              LogTextCtrl->AppendText(wxString("Started fs_kit computation\n", wxConvUTF8));
+               wrapper = new GUIWrapper(encodeOptions(), LogTextCtrl);
+               wrapper->Run();
+               delete wrapper;
+               wrapper = 0;
+-              LogTextCtrl->AppendText("Finished fs_kit computation\n");
+-              Start->SetLabel("Start");
++              LogTextCtrl->AppendText(wxString("Finished fs_kit computation\n", wxConvUTF8));
++            Start->SetLabel(wxString("Start", wxConvUTF8));
+               toppanel->Enable();
+          }
+          else
+@@ -466,7 +476,7 @@ void guiFrame::readOptions()
+ {
+     // create options object
+     string o = "";
+-    o += "-o \"" + SettingsCombo->GetValue() + "\"\n";
++    o += "-o \"" + std::string(SettingsCombo->GetValue().mb_str()) + "\"\n";
+     Options *options = new Options(o, LogTextCtrl);
+     chkAlign->SetValue(options->processAlign);
+@@ -474,13 +484,13 @@ void guiFrame::readOptions()
+     chkClassify->SetValue(options->processPC);
+     chkSelect->SetValue(options->processSelect);
+-    SpectraCombo->SetValue(options->inputFileList.c_str());
++    SpectraCombo->SetValue(wxString(options->inputFileList.c_str(), wxConvUTF8));
+     LogLevelCtrl->SetValue(options->logLevel);
+     LogLevelLbl->SetLabel(DescribeLogLevel(LogLevelCtrl->GetValue()));
+     // split up experiment name into path and file name
+-    wxFileName en = wxFileName(options->experimentName.c_str());
++    wxFileName en = wxFileName(wxString(options->experimentName.c_str(), wxConvUTF8));
+     OutputDirectoryCombo->SetValue(en.GetPath(wxPATH_GET_VOLUME));
+     ExperimentNameCombo->SetValue(en.GetName());
+@@ -492,7 +502,7 @@ string guiFrame::encodeOptions()
+     string o = "";
+     // settings file should be read at first, hence put it in front
+-    o += "-o \"" + SettingsCombo->GetValue() + "\"\n";
++    o += "-o \"" + std::string(SettingsCombo->GetValue().mb_str()) + "\"\n";
+     // the following options will override those in the settings file
+     o += "-align " + string(chkAlign->IsChecked() ? "1" : "0") + "\n";
+@@ -502,19 +512,19 @@ string guiFrame::encodeOptions()
+     o += "-log_level " + Options::int2string(LogLevelCtrl->GetValue()) + "\n";
+-    if (!SpectraCombo->GetValue().empty()) o += "-files_list \"" + SpectraCombo->GetValue() + "\"\n";
++    if (!SpectraCombo->GetValue().empty()) o += "-files_list \"" + std::string(SpectraCombo->GetValue().mb_str()) + "\"\n";
+     if (!ExperimentNameCombo->GetValue().empty()) 
+     {
+         o += "-experiment_name \"";
+         
+         if (!OutputDirectoryCombo->GetValue().empty()) 
+         {
+-             o += OutputDirectoryCombo->GetValue();
++             o += std::string(OutputDirectoryCombo->GetValue().mb_str());
+              if (OutputDirectoryCombo->GetValue().Last() != wxFileName::GetPathSeparator())
+                  o += wxFileName::GetPathSeparator();
+-        }                          
++        }
+                                
+-        o += ExperimentNameCombo->GetValue() + "\"\n";
++        o += std::string(ExperimentNameCombo->GetValue().mb_str()) + "\"\n";
+     }
+     // "-log_level"
+@@ -525,5 +535,3 @@ string guiFrame::encodeOptions()
+ #endif // fs_gui_wxwidgets
+-
+-
+diff --git a/src/fs_gui_layout.h b/src/fs_gui_layout.h
+index b569bbc..c569ec0 100644
+--- a/src/fs_gui_layout.h
++++ b/src/fs_gui_layout.h
+@@ -1,4 +1,4 @@
+-// -*- C++ -*- generated by wxGlade 0.3.1 on Sat Feb 14 18:44:55 2004
++// -*- C++ -*- generated by wxGlade 0.6.3 on Tue Oct 21 13:38:33 2008
+ // DO NOT EDIT BETWEEN "begin wxGlade" AND "end wxGlade"
+ /* fs_kit
+@@ -31,11 +31,15 @@
+ #include <wx/notebook.h>
+ // end wxGlade
++
+ #ifndef FS_GUI_LAYOUT_H
+ #define FS_GUI_LAYOUT_H
+ #include "fs_gui_wrapper.h"
++// begin wxGlade: ::extracode
++// end wxGlade
++
+ class guiFrame: public wxFrame {
+ public:
+@@ -55,7 +59,7 @@ private:
+     void set_properties();
+     void do_layout();
+     // end wxGlade
+-
++    
+ protected:
+     // begin wxGlade: guiFrame::attributes
+     wxMenuBar* frame_menubar;
+@@ -93,14 +97,14 @@ protected:
+     wxPanel* notebook_pane_2;
+     wxNotebook* notebook;
+     // end wxGlade
+-    
++
+     GUIWrapper* wrapper;
+-    
++  
+     string encodeOptions();
+     void readOptions();
+     
+     DECLARE_EVENT_TABLE()
+-};
++}; // wxGlade: end class
+ #endif // FS_GUI_LAYOUT_H
+diff --git a/src/fs_kit_driver.cpp b/src/fs_kit_driver.cpp
+index 1251e3e..d9df296 100644
+--- a/src/fs_kit_driver.cpp
++++ b/src/fs_kit_driver.cpp
+@@ -17,6 +17,7 @@
+  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+  */
++#include "fs_kit_options.h" // logger
+ #include "fs_kit_driver.h" 
+ int fs_driver::fsDriver::doRun () {
+@@ -30,60 +31,73 @@ int fs_driver::fsDriver::doRun () {
+     if (!options->processSP) {
+         if (options->processFit) {
+     
+-            if (options->logLevel >= 0) { ostringstream log; log << "process FIT ..."; *options->stdOut << log.str().c_str(); }
++            if (options->logLevel >= 0)
++                *options->stdOut << "process FIT ...";
+  
+             clock_t start = clock(), end; 
+     
+             fs_fit::FitFrontend fitfrontend(*options);
+             fitfrontend.processFit();
+-    
++          
+             end = clock();
+             const double elapsed = ((double) (end - start)) / CLOCKS_PER_SEC;
+-            if (options->logLevel >= 0) { ostringstream log; log << " done in " << setw(5) << elapsed << " seconds" << endl; *options->stdOut << log.str().c_str(); }
++          if (options->logLevel >= 0)
++              *options->stdOut << " done in " << setw(5) << elapsed << " seconds" << endl;
+         }
+         if (options->processAlign) {
+     
+-            if (options->logLevel >= 0) { ostringstream log; log << "process ALIGN ..."; *options->stdOut << log.str().c_str(); }
++            if (options->logLevel >= 0)
++            *options->stdOut << "process ALIGN ...";
++
+             clock_t start = clock(), end; 
+     
+-            if (options->logLevel >= 2) { ostringstream log; log << " initializing ..."; *options->stdOut << log.str().c_str(); }
++            if (options->logLevel >= 2)
++            *options->stdOut << " initializing ...";
+             fs_align::ClusterDriver acd(*options);
+-            if (options->logLevel >= 2) { ostringstream log; log << " clustering spectra ..."; *options->stdOut << log.str().c_str(); }
++            if (options->logLevel >= 2)
++            *options->stdOut << " clustering spectra ...";
+             acd.doClustering();
+-            if (options->logLevel >= 2) { ostringstream log; log << " aligning spectra ..."; *options->stdOut << log.str().c_str(); }
++            if (options->logLevel >= 2)
++            *options->stdOut << " aligning spectra ...";
+             acd.alignSpectra();
+-            if (options->logLevel >= 2) { ostringstream log; log << " printing spectra ..."; *options->stdOut << log.str().c_str(); }
++            if (options->logLevel >= 2)
++            *options->stdOut << " printing spectra ...";
+             acd.printSpectra();
+     
+             end = clock();
+             const double elapsed = ((double) (end - start)) / CLOCKS_PER_SEC;
+-            if (options->logLevel >= 0) { ostringstream log; log << " done in " << setw(5) << elapsed << " seconds" << endl; *options->stdOut << log.str().c_str(); }
++            if (options->logLevel >= 0)
++            *options->stdOut << " done in " << setw(5) << elapsed << " seconds" << endl;
+         }
+     
+         // todo: the selection logic should be moved out to e.g. fs_select_driver
+         if (options->processSelect) {
+         
+-            if (options->logLevel >= 0) { ostringstream log; log << "process SELECT"; *options->stdOut << log.str().c_str(); }
++            if (options->logLevel >= 0)
++            *options->stdOut << "process SELECT";
+     
+             clock_t start = clock(), end; 
+     
+             fs_select::Tree t(*options);
+     
+             double d = options->selectAvg * t.getAvg() + options->selectSD * t.getSD() + options->selectAbs;
+-            if (options->logLevel >= 0) { ostringstream log; log << " (merge_distance: " << d << ") ..."; *options->stdOut << log.str().c_str(); }
++            if (options->logLevel >= 0)
++            *options->stdOut << " (merge_distance: " << d << ") ...";
+     
+             select_filenames = t.streamLeavesMaxD(t.getTop(), d);
+             select_filenames.push_front(options->getFileName(options->alignName, false));
+     
+             end = clock();
+             const double elapsed = ((double) (end - start)) / CLOCKS_PER_SEC;
+-            if (options->logLevel >= 0) { ostringstream log; log << " done in " << setw(5) << elapsed << " seconds" << endl; *options->stdOut << log.str().c_str(); }
++            if (options->logLevel >= 0)
++            *options->stdOut << " done in " << setw(5) << elapsed << " seconds" << endl;
+     
+             if (options->processPC) {
+     
+-                if (options->logLevel >= 0) { ostringstream log; log << "process PC ..."; *options->stdOut << log.str().c_str(); }
++                if (options->logLevel >= 0)
++                *options->stdOut << "process PC ...";
+     
+                 clock_t start = clock(), end; 
+     
+@@ -91,7 +105,7 @@ int fs_driver::fsDriver::doRun () {
+     
+                     string current = *it;
+     
+-                    { ostringstream log; log << endl << "\t" << current << " ..."; *options->stdOut << log.str().c_str(); }
++                  *options->stdOut << endl << "\t" << current << " ...";
+     
+                     fs_pc::ClusterDriver pc(current, *options);
+     
+@@ -108,7 +122,8 @@ int fs_driver::fsDriver::doRun () {
+     
+                 end = clock();
+                 const double elapsed = ((double) (end - start)) / CLOCKS_PER_SEC;
+-                if (options->logLevel >= 0) { ostringstream log; log << " done in " << setw(5) << elapsed << " seconds" << endl; *options->stdOut << log.str().c_str(); }
++                if (options->logLevel >= 0)
++                *options->stdOut << " done in " << setw(5) << elapsed << " seconds" << endl;
+             }
+     
+         } else {
+@@ -118,14 +133,15 @@ int fs_driver::fsDriver::doRun () {
+                 clock_t start = clock(), end; 
+                 if (options->pcFile == "") {
+-                    if (options->logLevel >= 0) { ostringstream log; log << "ERROR: no file for classification specified" << endl; *options->stdOut << log.str().c_str(); }
++                    if (options->logLevel >= 0)
++                    *options->stdOut << "ERROR: no file for classification specified" << endl;
+                     return 1;
+                 }
+     
+-                if (options->logLevel >= 0) { ostringstream log; log << "process PC ..."; *options->stdOut << log.str().c_str(); }
+-    
+-                if (options->logLevel >= 0) { ostringstream log; log << endl << "\t" << options->pcFile << " ..."; *options->stdOut << log.str().c_str(); }
+-    
++                if (options->logLevel >= 0) {
++                *options->stdOut << "process PC ...";
++                *options->stdOut << endl << "\t" << options->pcFile << " ...";
++              }
+                 fs_pc::ClusterDriver pc(options->pcFile, *options);
+     
+                 pc.doClustering();
+@@ -138,7 +154,8 @@ int fs_driver::fsDriver::doRun () {
+     
+                 end = clock();
+                 const double elapsed = ((double) (end - start)) / CLOCKS_PER_SEC;
+-                if (options->logLevel >= 0) { ostringstream log; log << " done in " << setw(5) << elapsed << " seconds" << endl; *options->stdOut << log.str().c_str(); }
++                if (options->logLevel >= 0)
++                *options->stdOut << " done in " << setw(5) << elapsed << " seconds" << endl;
+             }
+     
+         }
+@@ -147,18 +164,22 @@ int fs_driver::fsDriver::doRun () {
+     {
+         // options->processSP is set
+-        if (options->logLevel >= 0) { ostringstream log; log << "process SELECT"; *options->stdOut << log.str().c_str(); }
+-        if (options->logLevel >= 0) { ostringstream log; log << " (" << options->peakFile << " " << options->peakStr << ") ..."; *options->stdOut << log.str().c_str(); }
+-
++        if (options->logLevel >= 0)
++        *options->stdOut << "process SELECT";
++        if (options->logLevel >= 0)
++        *options->stdOut << " (" << options->peakFile << " " << options->peakStr << ") ...";
++      
+         SelectPeak sp;
+         sp.init(*options);
+         sp.processFile(options->peakFile);            
+-        if (options->logLevel >= 0) { ostringstream log; log << " done" << endl; *options->stdOut << log.str().c_str(); }
++        if (options->logLevel >= 0)
++        *options->stdOut << " done" << endl;
+     }
+-    if (options->logLevel >= 0) { ostringstream log; log << endl << "fs_kit done" << endl << endl << flush; *options->stdOut << log.str().c_str(); }
++    if (options->logLevel >= 0)
++      *options->stdOut << endl << "fs_kit done" << endl << endl << flush;
+     return 0;
+diff --git a/src/fs_kit_options.cpp b/src/fs_kit_options.cpp
+index 12849df..2f61b26 100644
+--- a/src/fs_kit_options.cpp
++++ b/src/fs_kit_options.cpp
+@@ -1,8 +1,11 @@
+ #include "fs_kit_options.h"
+ #ifdef fs_gui_wxwidgets
++#if wxHAS_TEXT_WINDOW_STREAM == 0
++#error "Your compiler does not support wxTextCtrl streams"
++#endif
+ Options::Options(string opt, wxTextCtrl* log) {
+-    stdOut = log;
++    stdOut = new ostream(log);
+     InitOptions(opt);
+ } 
+ #endif
+@@ -156,6 +159,7 @@ void Options::defaultOptions() {
+     logLevel = 1;
+     commonFields = 10;
++
+ }
+ string Options::int2string(int num, int cntr) {
+diff --git a/src/fs_kit_options.h b/src/fs_kit_options.h
+index f75c555..4fd957f 100644
+--- a/src/fs_kit_options.h
++++ b/src/fs_kit_options.h
+@@ -3,8 +3,8 @@
+ #include <fstream>
+ #include <iostream>
+-#include <map>
+ #include <sstream>
++#include <map>
+ #include <string>
+ #ifdef fs_gui_wxwidgets
+@@ -33,12 +33,7 @@ class Options {
+     
+ public:
+-// use TextCtrl if running in wxWindows to direct log output
+-#ifdef fs_gui_wxwidgets
+-    wxTextCtrl  *stdOut;
+-#else    
+-    ostream           *stdOut;
+-#endif
++    ostream *stdOut;
+     static string int2string(int num, int cntr = 0);
+@@ -112,6 +107,7 @@ public:
+     void      printOptions(ostream* out = 0, bool print_all = true, bool print_description = false);
+     void setStop(bool stop = true) { stopRequested = stop; }
++
+ };
+ #endif
+-- 
+1.5.4.3
+
diff --git a/posts/Open_source_force_spectroscopy/0004-Added-wxglade-entry-to-Makefile-for-regenerating-aut.patch b/posts/Open_source_force_spectroscopy/0004-Added-wxglade-entry-to-Makefile-for-regenerating-aut.patch
new file mode 100644 (file)
index 0000000..0b1bfad
--- /dev/null
@@ -0,0 +1,45 @@
+From 6375e1f233b9366ca0ba40fac785764df0a6edb2 Mon Sep 17 00:00:00 2001
+From: W. Trevor King <wking@drexel.edu>
+Date: Tue, 21 Oct 2008 19:57:03 -0400
+Subject: [PATCH] Added wxglade entry to Makefile for regenerating automatic code.
+
+Also updated Makefile defaults for my Linux installation.
+---
+ Makefile |   10 +++++++---
+ 1 files changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index ccb2e69..5edf183 100644
+--- a/Makefile
++++ b/Makefile
+@@ -13,16 +13,17 @@
+ # The following two lines can be determined by running:
+ # wx-config --cppflags
+-WX_CCFLAGS = -I/sw/lib/wx/include/mac-ansi-release-2.5 -I/sw/include/wx-2.5 -D__WXMAC__ -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES -DWX_PRECOMP -DNO_GCC_PRAGMA
++WX_CCFLAGS = -I/usr/lib/wx/include/gtk2-unicode-release-2.8 -I/usr/include/wx-2.8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES -D__WXGTK__
+ # wx-config --libs
+-WX_LIBS = -L/sw/lib  -L/sw/lib -framework QuickTime -framework IOKit -framework Carbon -framework Cocoa -framework System  -lwx_mac_xrc-2.5 -lwx_mac_html-2.5 -lwx_mac_adv-2.5 -lwx_mac_core-2.5 -lwx_base_carbon_xml-2.5 -lwx_base_carbon_net-2.5 -lwx_base_carbon-2.5
++WX_LIBS = -pthread -Wl,-Bsymbolic-functions  -lwx_gtk2u_richtext-2.8 -lwx_gtk2u_aui-2.8 -lwx_gtk2u_xrc-2.8 -lwx_gtk2u_qa-2.8 -lwx_gtk2u_html-2.8 -lwx_gtk2u_adv-2.8 -lwx_gtk2u_core-2.8 -lwx_baseu_xml-2.8 -lwx_baseu_net-2.8 -lwx_baseu-2.8 
+ # If fs_gui_wxwidgets is set, fs_kit gets compiled with the GUI 
+ WX_FSKITFLAG = -Dfs_gui_wxwidgets
+ CC = /usr/bin/gcc
+-CC_OPTIONS = -W -Wall -Wno-long-double -I/sw/include $(WX_FSKITFLAG) $(WX_CCFLAGS)
++#CC_OPTIONS = -W -Wall -Wno-long-double -I/sw/include $(WX_FSKITFLAG) $(WX_CCFLAGS)
++CC_OPTIONS = -W -Wall $(WX_FSKITFLAG) $(WX_CCFLAGS)
+ LNK_OPTIONS = -L/sw/lib -lgsl -lgslcblas -lstdc++ $(WX_LIBS)
+ #
+@@ -185,3 +186,6 @@ fs_select_tree.o : src/fs_select_tree.cpp
+ ##### END RUN ####
++
++src/fs_gui_layout.cpp : src/fs_gui.wxg
++      wxglade -g C++ -o src/fs_gui_layout src/fs_gui.wxg
+-- 
+1.5.4.3
+
diff --git a/posts/Open_source_force_spectroscopy/fs_kit_tutorial.pdf b/posts/Open_source_force_spectroscopy/fs_kit_tutorial.pdf
new file mode 100644 (file)
index 0000000..1a8b5b3
Binary files /dev/null and b/posts/Open_source_force_spectroscopy/fs_kit_tutorial.pdf differ