[med-svn] [pycorrfit] 01/03: Imported Upstream version 0.9.4+dfsg

Alex Mestiashvili malex-guest at moszumanska.debian.org
Mon Dec 14 09:36:01 UTC 2015


This is an automated email from the git hooks/post-receive script.

malex-guest pushed a commit to branch master
in repository pycorrfit.

commit e99f3ac014d83b7a29197cab496ee6670ccce7d3
Author: Alexandre Mestiashvili <alex at biotec.tu-dresden.de>
Date:   Mon Dec 14 10:16:56 2015 +0100

    Imported Upstream version 0.9.4+dfsg
---
 ChangeLog.txt                   |   8 ++
 PKG-INFO                        |  14 +--
 README.md                       |  14 +--
 Readme.txt                      |  10 +-
 doc/PyCorrFit_doc_content.tex   |  16 +--
 doc/README.md                   |   2 +-
 pycorrfit/doc.py                |   6 +-
 pycorrfit/fcs_data_set.py       |  11 +--
 pycorrfit/frontend.py           |  18 +++-
 pycorrfit/openfile.py           |  53 +++++++++-
 pycorrfit/page.py               |  41 ++++++--
 pycorrfit/tools/batchcontrol.py | 209 ++++++++++++++++++++++++++++++++--------
 pycorrfit/wxutils.py            |   6 +-
 setup.py                        |   6 +-
 14 files changed, 321 insertions(+), 93 deletions(-)

diff --git a/ChangeLog.txt b/ChangeLog.txt
index 013cd16..70ef36c 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,3 +1,11 @@
+0.9.4
+- Batch control allows to select individual parameters (#108)
+- Allow to exclude pages from batch fitting (#107)
+- Bugfixes:
+  - Fix `ValueError` in parameter display
+  - Possibly fixed error with `yaml.safe_dump`
+    on Mac OSx 10.8.5
+  - Make sure background is lower than signal (#137)
 0.9.3
 - Fitting: migrate to lmfit
   - This introduces a new dependency for building PyCorrFit.
diff --git a/PKG-INFO b/PKG-INFO
index 86dda8a..5396602 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -2,11 +2,11 @@ Metadata-Version: 1.0
 Name: pycorrfit
 Version: 0.8.0
 Summary: UNKNOWN
-Home-page: https://github.com/paulmueller/PyCorrFit
+Home-page: https://github.com/FCS-analysis/PyCorrFit
 Author: Paul Mueller
 Author-email: paul.mueller at biotec.tu-dresden.de
 License: GPL v2
-Description: ![PyCorrFit](https://raw.github.com/paulmueller/PyCorrFit/master/doc-src/Images/PyCorrFit_logo_dark.png)
+Description: ![PyCorrFit](https://raw.github.com/FCS-analysis/PyCorrFit/master/doc-src/Images/PyCorrFit_logo_dark.png)
         =========
         
         This repository contains the source code of PyCorrFit - a scientific tool for fitting
@@ -24,10 +24,10 @@ Description: ![PyCorrFit](https://raw.github.com/paulmueller/PyCorrFit/master/do
         information, visit the official homepage at http://pycorrfit.craban.de.
         
         
-        - [Download the latest version](https://github.com/paulmueller/PyCorrFit/releases)  
-        - [Documentation](https://github.com/paulmueller/PyCorrFit/raw/master/PyCorrFit_doc.pdf)
-        - [Run PyCorrFit from source](https://github.com/paulmueller/PyCorrFit/wiki/Running-PyCorrFit-from-source)
-        - [Write model functions](https://github.com/paulmueller/PyCorrFit/wiki/Writing-model-functions)
-        - [Need help?](https://github.com/paulmueller/PyCorrFit/wiki/Creating-a-new-issue)
+        - [Download the latest version](https://github.com/FCS-analysis/PyCorrFit/releases)  
+        - [Documentation](https://github.com/FCS-analysis/PyCorrFit/raw/master/PyCorrFit_doc.pdf)
+        - [Run PyCorrFit from source](https://github.com/FCS-analysis/PyCorrFit/wiki/Running-PyCorrFit-from-source)
+        - [Write model functions](https://github.com/FCS-analysis/PyCorrFit/wiki/Writing-model-functions)
+        - [Need help?](https://github.com/FCS-analysis/PyCorrFit/wiki/Creating-a-new-issue)
         
 Platform: UNKNOWN
diff --git a/README.md b/README.md
index c38b4c7..cb20f3b 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
-![PyCorrFit](https://raw.github.com/paulmueller/PyCorrFit/master/doc/Images/PyCorrFit_logo_dark.png)
+![PyCorrFit](https://raw.github.com/FCS-analysis/PyCorrFit/master/doc/Images/PyCorrFit_logo_dark.png)
 =========
 [![PyPI](http://img.shields.io/pypi/v/PyCorrFit.svg)](https://pypi.python.org/pypi/pycorrfit)
 [![Build Win](https://img.shields.io/appveyor/ci/paulmueller/PyCorrFit/master.svg?label=build_win)](https://ci.appveyor.com/project/paulmueller/pycorrfit)
-[![Build Mac](https://img.shields.io/travis/paulmueller/PyCorrFit/master.svg?label=build_mac)](https://travis-ci.org/paulmueller/PyCorrFit)
+[![Build Mac](https://img.shields.io/travis/FCS-analysis/PyCorrFit/master.svg?label=build_mac)](https://travis-ci.org/FCS-analysis/PyCorrFit)
 
 
 
@@ -21,8 +21,8 @@ with different excitation geometries like total internal reflection (TIR). For m
 information, visit the official homepage at http://pycorrfit.craban.de.
 
 
-- [Download the latest version](https://github.com/paulmueller/PyCorrFit/releases)  
-- [Documentation](https://github.com/paulmueller/PyCorrFit/wiki/PyCorrFit_doc.pdf)
-- [Run PyCorrFit from source](https://github.com/paulmueller/PyCorrFit/wiki/Running-from-source)
-- [Write your own model functions](https://github.com/paulmueller/PyCorrFit/wiki/Writing-model-functions)
-- [Need help?](https://github.com/paulmueller/PyCorrFit/wiki/Creating-a-new-issue)
+- [Download the latest version](https://github.com/FCS-analysis/PyCorrFit/releases)  
+- [Documentation](https://github.com/FCS-analysis/PyCorrFit/wiki/PyCorrFit_doc.pdf)
+- [Run PyCorrFit from source](https://github.com/FCS-analysis/PyCorrFit/wiki/Running-from-source)
+- [Write your own model functions](https://github.com/FCS-analysis/PyCorrFit/wiki/Writing-model-functions)
+- [Need help?](https://github.com/FCS-analysis/PyCorrFit/wiki/Creating-a-new-issue)
diff --git a/Readme.txt b/Readme.txt
index 3548526..e48aa40 100644
--- a/Readme.txt
+++ b/Readme.txt
@@ -18,11 +18,11 @@ This package provides the Python module `pycorrfit` and its graphical user inter
 graphical user interface is written with wxPython. A HowTo for the installation of the 
 latest version of PyCorrFit using pip can be found there:
 
-https://github.com/paulmueller/PyCorrFit/wiki/Installation_pip
+https://github.com/FCS-analysis/PyCorrFit/wiki/Installation_pip
 
 Further reading:
 
-- Latest downloads: https://github.com/paulmueller/PyCorrFit/releases   
-- Documentation: https://github.com/paulmueller/PyCorrFit/wiki/PyCorrFit_doc.pdf  
-- Write model functions: https://github.com/paulmueller/PyCorrFit/wiki/Writing-model-functions   
-- Need help? https://github.com/paulmueller/PyCorrFit/wiki/Creating-a-new-issue   
+- Latest downloads: https://github.com/FCS-analysis/PyCorrFit/releases   
+- Documentation: https://github.com/FCS-analysis/PyCorrFit/wiki/PyCorrFit_doc.pdf  
+- Write model functions: https://github.com/FCS-analysis/PyCorrFit/wiki/Writing-model-functions   
+- Need help? https://github.com/FCS-analysis/PyCorrFit/wiki/Creating-a-new-issue   
diff --git a/doc/PyCorrFit_doc_content.tex b/doc/PyCorrFit_doc_content.tex
index f5c0d75..5ec10d5 100755
--- a/doc/PyCorrFit_doc_content.tex
+++ b/doc/PyCorrFit_doc_content.tex
@@ -2,7 +2,7 @@
 \label{sec:intro}
 \subsection{Preface}
 \label{sec:intro.prefa}
-\textit{PyCorrFit} emerged from my work in the Schwille Lab\footnote{\url{http://www.biochem.mpg.de/en/rd/schwille/}} at the Biotechnology Center of the TU Dresden in 2011/2012. Since then, the program has been further developed based on numerous input from FCS users, in particular Franziska Thomas, Grzesiek Chwastek, Janine Tittel, and Thomas Weidemann. The program source code is available at GitHub\footnote{\url{https://github.com/paulmueller/PyCorrFit}}. Please do not hesitate to sign [...]
+\textit{PyCorrFit} emerged from my work in the Schwille Lab\footnote{\url{http://www.biochem.mpg.de/en/rd/schwille/}} at the Biotechnology Center of the TU Dresden in 2011/2012. Since then, the program has been further developed based on numerous input from FCS users, in particular Franziska Thomas, Grzesiek Chwastek, Janine Tittel, and Thomas Weidemann. The program source code is available at GitHub\footnote{\url{https://github.com/FCS-analysis/PyCorrFit}}. Please do not hesitate to sig [...]
 
 \noindent \textit{PyCorrFit} was written to simplify the work with experimentally obtained correlation curves. These can be processed independently (operating system, location, time). PyCorrFit supports commonly used file formats and enables users to allocate and organize their data in a simple way.\\
 
@@ -54,10 +54,10 @@ Binary files for MacOS X 10.9.5 and later are available from the download page.
 For Windows XP and later, stand-alone binary executables are available from the download page. 
 \item \textbf{Ubuntu/Debian.}
 PyCorrFit is available from the Debian repositories and can be installed via the operating systems packaging tool (e.g. \texttt{apt-get install pycorrfit}).
-\item\textbf{PyPI.} To run \textit{PyCorrFit} on any other operating system, the installation of Python v.2.7 is required. \textit{PyCorrFit} is included in the Python package index (PyPI, \url{http://pypi.python.org/pypi/pip}) and can be installed via\footnote{See also the wiki article at \url{https://github.com/paulmueller/PyCorrFit/wiki/Installation_pip}}
+\item\textbf{PyPI.} To run \textit{PyCorrFit} on any other operating system, the installation of Python v.2.7 is required. \textit{PyCorrFit} is included in the Python package index (PyPI, \url{http://pypi.python.org/pypi/pip}) and can be installed via\footnote{See also the wiki article at \url{https://github.com/FCS-analysis/PyCorrFit/wiki/Installation_pip}}
 \texttt{pip~install~pycorrfit$\!$[GUI]}.
 \item \textbf{Sources.}
-You can also directly download the source code at any developmental stage\footnote{See also the wiki article at \url{https://github.com/paulmueller/PyCorrFit/wiki/Running-from-source}}.
+You can also directly download the source code at any developmental stage\footnote{See also the wiki article at \url{https://github.com/FCS-analysis/PyCorrFit/wiki/Running-from-source}}.
 \end{itemize}
 
 
@@ -203,10 +203,14 @@ The tool is closed by the button \textit{Cancel}. All the listed data sets will
 \label{sec:menub.tools.batch}
 By default, the current page is taken as a reference to perform automated fitting. A batch is defined as the ensemble of correlation data sets (pages) assigned to the same model function within a session. A session can therefore have several batches, even for the same data. 
 
-For fitting, it is crucial to carefully define the starting parameters, whether parameters should be fixed or varied, the range of values which make physically sense, and other options offered within the \textit{Main window}. By executing \textit{Apply to applicable pages}, these settings are transferred to all other pages assigned to the same fit model. Note that this includes the range of lag times (lag time channels) which may have been changed with the \textit{Data range }tool for in [...]
+For fitting, it is crucial to carefully define the starting parameters, whether parameters should be fixed or varied, the range of values which make physically sense, and other options offered within the \textit{Main window}. By executing \textit{Apply to applicable pages}, these settings are transferred to all other pages assigned to the same fit model. Note that this includes the range of lag times (lag time channels) which may have been changed with the \textit{Data range} tool for in [...]
+
+It is possible to prevent the application of fitting parameters to individual pages by checking the \textit{prevent batch modification} checkbox in the \textit{Model parameters} box of a page.
 
 The button \textit{Fit applicable pages} then performs fitting on all pages of the same batch. Alternatively, the user can define an external source of parameters as a reference, i.e. the first page of some \textit{Other session} (*.pcfs). However, this assumes a consistent assignment of model functions.
 
+
+
 \subsubsection{Tools / Global fitting}
 \label{sec:menub.tools.globa}
 Global fitting is useful when experimental curves share the same values for certain physical parameters. For example, due to physical constraints in two-focus FCS both autocorrelation curves and  cross-correlation curves should adopt the same values for the diffusion time $\tau_\mathrm{diff}$ and the number of particles $n$. A global fit can be applied such that $n$ and $\tau_\mathrm{diff}$ are identical for all data sets. All curves are added to a single array. In contrast to fixing the [...]
@@ -731,6 +735,6 @@ PyCorrFit can utilize several algorithms to perform this minimization. The descr
 \input{PyCorrFit_doc_models}
 
 \section{Troubleshooting}
-If you are having problems with PyCorrFit, you might find the solution in the frequently asked questions\footnote{\url{https://github.com/paulmueller/PyCorrFit/wiki/Frequently-Asked-Questions-\%28FAQ\%29}} or on other pages in the \textit{PyCorrFit} 
-wiki\footnote{\url{https://github.com/paulmueller/PyCorrFit/wiki}}.
+If you are having problems with PyCorrFit, you might find the solution in the frequently asked questions\footnote{\url{https://github.com/FCS-analysis/PyCorrFit/wiki/Frequently-Asked-Questions-\%28FAQ\%29}} or on other pages in the \textit{PyCorrFit} 
+wiki\footnote{\url{https://github.com/FCS-analysis/PyCorrFit/wiki}}.
 There you will also find instructions on how to contact us to file a bug or to request a feature.
diff --git a/doc/README.md b/doc/README.md
index 0afe7cf..a8c53ba 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -1,5 +1,5 @@
 This folder contains the TeX-source of the 
-[PyCorrFit documentation](https://github.com/paulmueller/PyCorrFit/wiki/PyCorrFit_doc.pdf).
+[PyCorrFit documentation](https://github.com/FCS-analysis/PyCorrFit/wiki/PyCorrFit_doc.pdf).
 
 If, for some reason, you wish to compile it yourself, you will need a 
 working LaTeX distribution.
diff --git a/pycorrfit/doc.py b/pycorrfit/doc.py
index 00e09fc..7eedd12 100755
--- a/pycorrfit/doc.py
+++ b/pycorrfit/doc.py
@@ -185,6 +185,6 @@ except:
     
     
 # Github homepage
-GitChLog = "https://raw.github.com/paulmueller/PyCorrFit/master/ChangeLog.txt"
-GitHome = "https://github.com/paulmueller/PyCorrFit"
-GitWiki = "https://github.com/paulmueller/PyCorrFit/wiki"
+GitChLog = "https://raw.github.com/FCS-analysis/PyCorrFit/master/ChangeLog.txt"
+GitHome = "https://github.com/FCS-analysis/PyCorrFit"
+GitWiki = "https://github.com/FCS-analysis/PyCorrFit/wiki"
diff --git a/pycorrfit/fcs_data_set.py b/pycorrfit/fcs_data_set.py
index cde3b93..3deaa0f 100644
--- a/pycorrfit/fcs_data_set.py
+++ b/pycorrfit/fcs_data_set.py
@@ -188,8 +188,6 @@ class Correlation(object):
         self.fit_weight_type = fit_weight_type
         self.fit_weight_parameters = fit_weight_data
     
-        # lock prevents any changes to the parameters
-        self.lock_parameters = False
         self.normparm = normparm
         self.title = title
         self.traces = traces
@@ -452,17 +450,16 @@ class Correlation(object):
     @property
     def fit_parameters(self):
         """parameters that were fitted/will be used for fitting"""
+        # Do not return `self._fit_parameters.copy()`, because
+        # some methods of PyCorrFit depende on the array being
+        # accessible and changeable with indices.
         return self._fit_parameters
 
     @fit_parameters.setter
     def fit_parameters(self, value):
         # must unlock parameters, if change is required
         value = np.array(value)
-        if self.lock_parameters == False:
-            self._fit_parameters = self.check_parms(value)
-        else:
-            warnings.warn("Correlation {}: fixed parameters unchanged.".
-                          format(self.uid))
+        self._fit_parameters = self.check_parms(value)
 
     @property
     def fit_parameters_range(self):
diff --git a/pycorrfit/frontend.py b/pycorrfit/frontend.py
index 4318059..1ef782d 100644
--- a/pycorrfit/frontend.py
+++ b/pycorrfit/frontend.py
@@ -1429,9 +1429,17 @@ class MyFrame(wx.Frame):
         except:
             pass
         try:
-            Infodict["Preferences"] # not used yet
+            prefdict = Infodict["Preferences"]
         except:
             pass
+        else:
+            for key in prefdict:
+                if key == "Pages prevent batch modification":
+                    for pid in prefdict[key]:
+                        for i in np.arange(N):
+                            page = self.notebook.GetPage(i)
+                            if page.counter.strip("#: ") == pid:
+                                page.prevent_batch_modification = True
         if self.notebook.GetPageCount() > 0:
             # Enable the "Current" Menu
             self.EnableToolCurrent(True)
@@ -1591,6 +1599,14 @@ class MyFrame(wx.Frame):
             Infodict["External Weights"][counter] = external_weights
         # Append Session Comment:
         Infodict["Comments"]["Session"] = self.SessionComment
+        # Protected pages:
+        protpage = []
+        for i in np.arange(N):
+            # Set Page 
+            Page = self.notebook.GetPage(i)
+            if Page.prevent_batch_modification:
+                protpage.append(Page.counter.strip("#: "))
+        Infodict["Preferences"]["Pages prevent batch modification"] = protpage
         # File dialog
         dlg = wx.FileDialog(self, "Save session file", self.dirname, "",
                             "PyCorrFit session (*.pcfs)|*.pcfs|All files (*.*)|*.*",
diff --git a/pycorrfit/openfile.py b/pycorrfit/openfile.py
index 9b797f1..85ee8db 100644
--- a/pycorrfit/openfile.py
+++ b/pycorrfit/openfile.py
@@ -258,6 +258,28 @@ def LoadSessionData(sessionfile, parameters_only=False):
                     Wdata.append(np.float(row[0]))
             Weightsdict[pageid][Nkey] = np.array(Wdata)
         Infodict["External Weights"] = Weightsdict
+    ## Preferences
+    preferencesname = "preferences.cfg"
+    try:
+        # Raises KeyError, if file is not present:
+        Arc.getinfo(preferencesname)
+    except:
+        pass
+    else:
+        prefdict = {}
+        with Arc.open(preferencesname) as fd:
+            data = fd.readlines()
+        for line in data:
+            line = line.strip()
+            if len(line) == 0 or line.startswith("#"):
+                continue
+            key, value = line.split("=")
+            key = key.strip()
+            value = value.strip()
+            if value.count(","):
+                value = [ v.strip() for v in value.split(",")]
+            prefdict[key] = value
+        Infodict["Preferences"] = prefdict
     Arc.close()
     return Infodict
 
@@ -278,7 +300,7 @@ def SaveSessionData(sessionfile, Infodict):
         "External Functions, dict": modelids to external model functions
         "External Weights", dict: page numbers, external weights for fitting
         "Parameters", dict: page numbers, all parameters of the pages
-        "Preferences", dict: not used yet
+        "Preferences", dict: fixed page parameters
         "Traces", dict: page numbers, all traces of the pages
 
 
@@ -311,7 +333,22 @@ def SaveSessionData(sessionfile, Infodict):
         # Range of fitting parameters
         Parms[idparm][9] = np.array(Parms[idparm][9],dtype="float").tolist()
         Parmlist.append(Parms[idparm])
-    yaml.safe_dump(Parmlist, open(parmsfilename, "wb"))
+    try:
+        # We would like to perform safe_dump, because in the
+        # Windoes x64 version, some integers are exported
+        # like this: `!!python/long '105'` using `yaml.dump`.
+        with open(parmsfilename, "wb") as yamlfd:
+            yaml.safe_dump(Parmlist, yamlfd)
+    except:# yaml.representer.RepresenterError:
+        # This error occured once on Mac OS 10.8.5:
+        # `RepresenterError: cannot represent an object: 0`
+        # In this case, we choose to use the normal dump
+        # and pray.
+        if os.path.exists(parmsfilename):
+            os.remove(parmsfilename)
+        with open(parmsfilename, "wb") as yamlfd:
+            yaml.dump(Parmlist, yamlfd)
+        
     Arc.write(parmsfilename)
     os.remove(os.path.join(tempdir, parmsfilename))
     # Supplementary data (errors of fit)
@@ -493,6 +530,18 @@ def SaveSessionData(sessionfile, Infodict):
     WeightFile.close()
     Arc.write(WeightFilename)
     os.remove(os.path.join(tempdir, WeightFilename))
+    ## Preferences
+    preferencesname = "preferences.cfg"
+    with open(preferencesname, 'w') as fd:
+        for key in Infodict["Preferences"]:
+            value = Infodict["Preferences"][key]
+            if isinstance(value, list):
+                value = " ".join("{}".format(it) for it in value)
+            else:
+                value = "{}".format(value)
+            fd.write("{} = {}\n".format(key, value))
+    Arc.write(preferencesname)
+    os.remove(os.path.join(tempdir, preferencesname))
     ## Readme
     rmfilename = "Readme.txt"
     rmfile = open(rmfilename, 'wb')
diff --git a/pycorrfit/page.py b/pycorrfit/page.py
index 868a059..07f14b6 100644
--- a/pycorrfit/page.py
+++ b/pycorrfit/page.py
@@ -133,6 +133,14 @@ class FittingPanel(wx.Panel):
         return self.corr.fit_model.id
     
     @property
+    def prevent_batch_modification(self):
+        return self.wxCBPreventBatchParms.GetValue()
+    
+    @prevent_batch_modification.setter
+    def prevent_batch_modification(self, value):
+        self.wxCBPreventBatchParms.SetValue(value)
+    
+    @property
     def title(self):
         return self.tabtitle.GetValue()
 
@@ -507,15 +515,27 @@ class FittingPanel(wx.Panel):
         #                       normtoNDropdown, textnor]
         if self.corr.is_cc:
             # update both self.bgselected and self.bg2selected
-            bg = [self.AmplitudeInfo[1][0].GetValue(),
-                  self.AmplitudeInfo[1][1].GetValue()]
-            tools.background.ApplyAutomaticBackground(self, bg,
-                                                      self.parent)
+            bg = [float(self.AmplitudeInfo[1][0].GetValue()),
+                  float(self.AmplitudeInfo[1][1].GetValue())]
+            sig = [float(self.AmplitudeInfo[0][0].GetValue()),
+                  float(self.AmplitudeInfo[0][1].GetValue())]
+            # Make sure bg < sig
+            for ii in range(len(bg)):
+                if sig[ii] != 0:
+                    if bg[ii] > .99*sig[ii]:
+                        bg[ii] = .99*sig[ii]
+                        self.AmplitudeInfo[1][ii].SetValue(bg[ii])
         else:
             # Only update self.bgselected 
-            bg = self.AmplitudeInfo[1][0].GetValue()
-            tools.background.ApplyAutomaticBackground(self, bg,
-                                                      self.parent)
+            bg = float(self.AmplitudeInfo[1][0].GetValue())
+            sig = float(self.AmplitudeInfo[0][0].GetValue())
+            # Make sure bg < sig
+            if sig != 0:
+                if bg > .99*sig:
+                    bg = .99*sig
+                    self.AmplitudeInfo[1][0].SetValue(bg)
+        tools.background.ApplyAutomaticBackground(self, bg,
+                                                  self.parent)
         e.Skip()
 
     
@@ -740,7 +760,12 @@ class FittingPanel(wx.Panel):
         self.panelsettings.sizer = wx.BoxSizer(wx.VERTICAL)
         self.panelsettings.sizer.Add(sizerti)
         self.panelsettings.sizer.Add(box1)
-        # Add button "Apply" and "Set range"
+        # checkbox "Protect from batch control"
+        self.wxCBPreventBatchParms = wx.CheckBox(self.panelsettings,
+                                                 -1,
+                                                 "prevent batch modification")
+        box1.Add(self.wxCBPreventBatchParms)
+        # buttons "Apply" and "Set range"
         horzs = wx.BoxSizer(wx.HORIZONTAL)
         buttonapply = wx.Button(self.panelsettings, label="Apply")
         self.Bind(wx.EVT_BUTTON, self.PlotAll, buttonapply)
diff --git a/pycorrfit/tools/batchcontrol.py b/pycorrfit/tools/batchcontrol.py
index 9b89b4b..727a4cd 100644
--- a/pycorrfit/tools/batchcontrol.py
+++ b/pycorrfit/tools/batchcontrol.py
@@ -30,52 +30,24 @@ class BatchCtrl(wx.Frame):
         ## MYID
         # This ID is given by the parent for an instance of this class
         self.MyID = None
+        ## Misc
+        try:
+            self.curpage = self.parent.notebook.GetCurrentPage()
+        except:
+            self.curpage = None
         ## Controls
         panel = wx.Panel(self)
         self.panel = panel
-        text1 = wx.StaticText(panel, label="Choose source of parameters:")
-        self.rbtnhere = wx.RadioButton(panel, -1, 'This session', 
-                                        style = wx.RB_GROUP)
-        self.rbtnhere.SetValue(True)
-        self.rbtnthere = wx.RadioButton(panel, -1, 'Other session')
-        self.dropdown = wx.ComboBox(panel, -1, "Current page", (15, 30),
-                         wx.DefaultSize, [], wx.CB_DROPDOWN|wx.CB_READONLY)
-        # Create the dropdownlist
-        self.OnPageChanged()
-        text2 = wx.StaticText(panel, label='This will affect all pages'+
-                                           '\nwith the same model.'+
-                                           '\nApply parameters:')
-        btnapply = wx.Button(panel, wx.ID_ANY, 'Apply to applicable pages')
-        btnfit = wx.Button(panel, wx.ID_ANY, 'Fit applicable pages')
-        # Bindings
-        self.Bind(wx.EVT_BUTTON, self.OnApply, btnapply)
-        self.Bind(wx.EVT_BUTTON, self.OnFit, btnfit)
-        self.Bind(wx.EVT_RADIOBUTTON, self.OnRadioHere, self.rbtnhere)
-        self.Bind(wx.EVT_RADIOBUTTON, self.OnRadioThere, self.rbtnthere)
-        # self.Bind(wx.EVT_COMBOBOX, self.OnSelect, self.dropdown)
-        topSizer = wx.BoxSizer(wx.VERTICAL)
-        topSizer.Add(text1)
-        topSizer.Add(self.rbtnhere)
-        topSizer.Add(self.rbtnthere)
-        topSizer.AddSpacer(5)
-        topSizer.Add(self.dropdown)
-        topSizer.AddSpacer(5)
-        topSizer.Add(text2)
-        topSizer.AddSpacer(5)
-        topSizer.Add(btnapply)
-        topSizer.Add(btnfit)
-        panel.SetSizer(topSizer)
-        topSizer.Fit(self)
-        self.SetMinSize(topSizer.GetMinSizeTuple())
-        # Check if we even have pages.
-        self.OnPageChanged()
         #Icon
+        self.Redraw()
         if parent.MainIcon is not None:
             wx.Frame.SetIcon(self, parent.MainIcon)
         self.Show(True)
 
-
-    def OnApply(self, event):
+    
+    def GetParameters(self):
+        """ The parameters
+        """
         # Get the item from the dropdown list
         item = self.dropdown.GetSelection()
         if self.rbtnhere.Value == True:
@@ -91,12 +63,37 @@ class BatchCtrl(wx.Frame):
         else:
             # Get Parameters from different session
             Parms = self.YamlParms[item]
+        return Parms
+
+
+    def GetProtectedParameterIDs(self):
+        """ The model parameters that are protected from batch control
+        
+        """
+        pbool = [ not cb.GetValue() for cb in self.wxParameterCheckBoxes ]
+        return np.array(pbool, dtype=bool)
+    
+    
+    def OnApply(self, event):
+        Parms = self.GetParameters()
         modelid = Parms[1]
         # Set all parameters for all pages
         for i in np.arange(self.parent.notebook.GetPageCount()):
             OtherPage = self.parent.notebook.GetPage(i)
-            if OtherPage.corr.fit_model.id == modelid and OtherPage.corr.correlation is not None:
+            if (OtherPage.corr.fit_model.id == modelid and
+                OtherPage.corr.correlation is not None):
+                # create a copy of the fitting parameters in
+                # case we want to protect them
+                proparms = OtherPage.corr.fit_parameters
                 self.parent.UnpackParameters(Parms, OtherPage)
+                if OtherPage.prevent_batch_modification:
+                    # write back protected parameters
+                    OtherPage.corr.fit_parameters = proparms
+                else:
+                    # write back only selected parameters
+                    pbool = self.GetProtectedParameterIDs()
+                    OtherPage.corr.fit_parameters[pbool] = proparms[pbool]
+                OtherPage.apply_parameters_reverse()
                 OtherPage.PlotAll(trigger="parm_batch")
         # Update all other tools fit the finalize trigger.
         self.parent.OnFNBPageChanged(trigger="parm_finalize")
@@ -141,13 +138,25 @@ class BatchCtrl(wx.Frame):
         """
         if self.parent.notebook.GetPageCount() == 0:
             self.panel.Disable()
+            # nothing to do
             return
         else:
             self.panel.Enable()
         # Filter triggers
-        if trigger in ["fit_batch", "fit_finalize",
+        if trigger in ["fit_batch", "fit_finalize", "init",
                        "parm_batch", "parm_finalize"]:
             return
+        
+        if Page is not None:
+            # redraw this tool if necessary
+            if self.curpage is not None:
+                oldmodelid = self.curpage.modelid
+            else:
+                oldmodelid = 0
+            newmodelid = Page.modelid
+            if oldmodelid != newmodelid:
+                self.RedrawParameterBox()
+
         # We need to update the list of Pages in self.dropdown
         if self.rbtnhere.Value == True:
             DDlist = list()
@@ -158,9 +167,12 @@ class BatchCtrl(wx.Frame):
             self.dropdown.SetItems(DDlist)
             self.dropdown.SetSelection(0)
 
+        self.curpage = self.parent.notebook.GetCurrentPage()
+
 
     def OnRadioHere(self, event=None):
         self.OnPageChanged(trigger="view")
+        self.RedrawParameterBox()
 
 
     def OnRadioThere(self, event=None):
@@ -192,3 +204,120 @@ class BatchCtrl(wx.Frame):
         self.dropdown.SetItems(DDlist)
         # Set selection text to first item
         self.dropdown.SetSelection(0)
+        self.RedrawParameterBox()
+
+
+    def Redraw(self, e=None):
+        panel = self.panel
+        for child in panel.GetChildren():
+            panel.RemoveChild(child)
+            child.Destroy()
+
+        ## Parameter source selection
+        boxleft = wx.StaticBox(panel, label="Parameter source")
+        self.rbtnhere = wx.RadioButton(panel, -1, 'This session', 
+                                        style = wx.RB_GROUP)
+        self.rbtnhere.SetValue(True)
+        self.rbtnthere = wx.RadioButton(panel, -1, 'Other session')
+        self.dropdown = wx.ComboBox(panel, -1, "Current page", (15, 30),
+                         wx.DefaultSize, [], wx.CB_DROPDOWN|wx.CB_READONLY)
+        # Create the dropdownlist
+        text2 = wx.StaticText(panel, label="""Only data sets that have the
+same model as the parameter
+source will be affected by
+batch modification, which
+includes parameter values as
+well as settings for fitting
+and background correction.
+To prevent batch modification
+of parameter values for an
+individual page, check its 
+"prevent batch modification"
+check box.""")
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnRadioHere, self.rbtnhere)
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnRadioThere, self.rbtnthere)
+        self.Bind(wx.EVT_COMBOBOX, self.RedrawParameterBox, self.dropdown)
+        leftSizer = wx.StaticBoxSizer(boxleft, wx.VERTICAL)
+        leftSizer.Add(self.rbtnhere)
+        leftSizer.Add(self.rbtnthere)
+        leftSizer.AddSpacer(5)
+        leftSizer.Add(self.dropdown)
+        leftSizer.AddSpacer(5)
+        leftSizer.Add(text2)
+        leftSizer.AddSpacer(5)
+
+        ## Parameter selection
+        boxright = wx.StaticBox(panel, label="Selected parameters")
+        rightSizer = wx.StaticBoxSizer(boxright, wx.VERTICAL)
+        boxright.SetSizer(rightSizer)
+        self.parameter_sizer = rightSizer
+        self.RedrawParameterBox()
+
+        ## Buttons
+        btnapply = wx.Button(panel, wx.ID_ANY, 'Apply to applicable pages')
+        btnfit = wx.Button(panel, wx.ID_ANY, 'Fit applicable pages')
+        # Bindings
+        self.Bind(wx.EVT_BUTTON, self.OnApply, btnapply)
+        self.Bind(wx.EVT_BUTTON, self.OnFit, btnfit)
+
+        ## Sizers
+        sizer_bag = wx.GridBagSizer(hgap=5, vgap=5)
+        sizer_bag.Add(leftSizer, (0,0))
+        sizer_bag.Add(rightSizer, (0,1))
+        horsizer = wx.BoxSizer(wx.HORIZONTAL)
+        horsizer.Add(btnapply)
+        horsizer.Add(btnfit)
+        sizer_bag.Add(horsizer, (1,0), span=wx.GBSpan(1,2))
+        
+        panel.SetSizer(sizer_bag)
+        sizer_bag.Fit(panel)
+        self.SetMinSize(sizer_bag.GetMinSizeTuple())
+        # Check if we even have pages.
+        self.OnPageChanged()
+        panel.Layout()
+        sizer_bag.Fit(self)
+        self.mastersizer = sizer_bag
+        
+
+    def RedrawParameterBox(self, e=None):
+        sizer = self.parameter_sizer
+        panel = self.panel
+        for child in sizer.GetChildren():
+            window = child.GetWindow()
+            panel.RemoveChild(window)
+            sizer.RemoveWindow(window)
+            window.Destroy()
+
+        text = wx.StaticText(panel, label="""If desired, (de)select
+individual parameters
+for batch modification.""")
+        sizer.Add(text)
+
+        if self.parent.notebook.GetPageCount():
+            # Get parameters of current page
+            parms = self.GetParameters()
+            modelid = parms[1]
+            ptext, _pval = mdls.GetHumanReadableParms(modelid, parms[2])
+            ptext = [ p.split()[0] for p in ptext ]
+            self.wxParameterCheckBoxes = []
+            for p in ptext:
+                cb = wx.CheckBox(panel, label=p)
+                cb.SetValue(True)
+                self.wxParameterCheckBoxes.append(cb)
+                sizer.Add(cb)
+
+        # Try to set sizes correctly
+        box = sizer.GetStaticBox()
+        boxs = box.GetBestSize()
+        sizs = sizer.GetMinSize()
+        thesize = (max(boxs[0], sizs[0]+20), sizs[1])
+        sizer.SetMinSize(thesize)
+        box.SetMinSize(thesize)
+        box.SetSize(thesize)
+
+        try:
+            self.mastersizer.Fit(panel)
+            panel.Layout()
+            self.SetSize(panel.GetSize())
+        except:
+            pass
\ No newline at end of file
diff --git a/pycorrfit/wxutils.py b/pycorrfit/wxutils.py
index 7e55c8c..f44d920 100644
--- a/pycorrfit/wxutils.py
+++ b/pycorrfit/wxutils.py
@@ -25,9 +25,9 @@ def float2string_nsf(fval, n=7):
             npoint=n
         else:
             q=abs(fval)
-            # prevent k from having negative values
-            k=max(0,int(np.ceil(np.log10(q/n))))
-            npoint = n-k
+            k=int(np.ceil(np.log10(q/n)))
+            # prevent negative significant digits
+            npoint = max(0, n-k)
         string="{:.{}f}".format(fval, npoint)
     except:
         string="{}".format(fval)
diff --git a/setup.py b/setup.py
index 7c45b74..ab7a44c 100644
--- a/setup.py
+++ b/setup.py
@@ -57,7 +57,7 @@ class PyTest(Command):
 
 # Download documentation if it was not compiled
 Documentation = join(dirname(realpath(__file__)), "doc/PyCorrFit_doc.pdf")
-webdoc = "https://github.com/paulmueller/PyCorrFit/wiki/PyCorrFit_doc.pdf"
+webdoc = "https://github.com/FCS-analysis/PyCorrFit/wiki/PyCorrFit_doc.pdf"
 if not exists(Documentation):
     print("Downloading {} from {}".format(Documentation, webdoc))
     import urllib
@@ -102,7 +102,7 @@ setup(
     long_description=open(join(dirname(__file__), 'Readme.txt')).read(),
     name=name,
     platforms=['ALL'],
-    url='https://github.com/paulmueller/PyCorrFit',
+    url='https://github.com/FCS-analysis/PyCorrFit',
     version=version,
     # data files
     packages=['pycorrfit',
@@ -131,7 +131,7 @@ setup(
         "NumPy >= 1.5.1",
         "SciPy >= 0.8.0",
         "PyYAML >= 3.09",
-        "lmfit",
+        "lmfit >= 0.9.2",
         ],
     setup_requires=["cython"],
     # scripts

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/pycorrfit.git



More information about the debian-med-commit mailing list