]> git.donarmstrong.com Git - neurodebian.git/commitdiff
Merge branch 'master' of alioth:/git/pkg-exppsy/neurodebian
authorMichael Hanke <michael.hanke@gmail.com>
Tue, 23 Nov 2010 14:12:46 +0000 (09:12 -0500)
committerMichael Hanke <michael.hanke@gmail.com>
Tue, 23 Nov 2010 14:12:46 +0000 (09:12 -0500)
* 'master' of alioth:/git/pkg-exppsy/neurodebian:
  added chronux entry
  adding relacs
  RF+NF: make it usable as a helper for reporting WNPP bugreports
  Added future/blends task files for relevant pkgs: just use ../../tools/blends-inject -v 5 *
  reenable Language -- many people already use it
  RF: blends-inject -- use Suggests (instead of Ignore) for "source-only" entries
  blends-inject: more consistency
  default exit code for error

future/blends/chronux [new file with mode: 0644]
future/blends/neurodata [new file with mode: 0644]
future/blends/qrtailab [new file with mode: 0644]
future/blends/relacs [new file with mode: 0644]
future/blends/spike [new file with mode: 0644]
future/blends/stimfit [new file with mode: 0644]
future/blends/trellis-neuro [new file with mode: 0644]
tools/blends-inject

diff --git a/future/blends/chronux b/future/blends/chronux
new file mode 100644 (file)
index 0000000..38dab93
--- /dev/null
@@ -0,0 +1,18 @@
+Source: chronus
+Tasks: debian-science/neuroscience-electrophysiology
+Homepage: http://www.chronux.org/
+License: GPL-2+
+Author: Gerald Dalley, Catherine Loader
+Language: C, Matlab/Octave
+Version: 2.00
+Pkg-Description: platform for analysis of neural signals
+ Chronux is a Matlab toolbox for signal processing of neural time
+ series data, several specialized mini-packages for spike sorting,
+ local regression, audio segmentation and other tasks. It also
+ includes a graphical user interface (GUI). The current version of
+ the GUI contains a number of features specialised to the analysis of
+ electroencephalography (EEG) data. The eventual aim is to provide
+ domain specific user interfaces (UIs) for each experimental modality,
+ along with corresponding data management tools.
+Remark: last release more than 2 years ago, and no major vital signs since then
+Registration: http://www.chronux.org/register/
diff --git a/future/blends/neurodata b/future/blends/neurodata
new file mode 100644 (file)
index 0000000..f5694b0
--- /dev/null
@@ -0,0 +1,11 @@
+Source: neurodata
+Tasks: debian-science/neuroscience-electrophysiology
+
+Homepage: http://sourceforge.net/projects/neurodata/
+Language: C++, Octave/Matlab, Perl
+Author: Bayle Shanks
+License: GPL-2+
+Pkg-Description: suite to analyze data acquired from electrophysiology experiments
+ Currently, neurodata has an Octave/MATLAB program to analyze
+ electroneurogram traces of coupled oscillators, and a Perl library
+ for the analysis of voltage trace data.
diff --git a/future/blends/qrtailab b/future/blends/qrtailab
new file mode 100644 (file)
index 0000000..8485f81
--- /dev/null
@@ -0,0 +1,11 @@
+Source: qrtailab
+Tasks: debian-science/neuroscience-electrophysiology
+Homepage: http://qrtailab.sourceforge.net/
+Author: Holger Nahrstaedt
+License: LGPL-2
+Why: Useful and used in acquisition/analysis setups
+Pkg-Description: Qt-GUI for RTAI
+ QRtaiLab is a QT-based port of the software scope xrtailab of the
+ RTAI project. It can be used as virtual oscilloscope and monitoring
+ application for interacting with the real-time external.
+Version: 0.1.12
diff --git a/future/blends/relacs b/future/blends/relacs
new file mode 100644 (file)
index 0000000..5bc4029
--- /dev/null
@@ -0,0 +1,35 @@
+Source: relacs
+Tasks: debian-science/neuroscience-electrophysiology
+Homepage: http://www.relacs.net
+License: GPL-2+
+Author: Jan Benda <benda@bio.lmu.de>
+Language: C++
+Version: 0.9.7
+WNPP: 604564
+Pkg-Description: framework for closed-loop neurophysiological experiments
+ RELACS is designed as an framework for closed-loop experiments that
+ may considerably speed up this traditional approach and in addition
+ offers novel experimental possibilities. In a closed-loop experiment
+ a stimulus is presented, the resulting response is immediately
+ analyzed, and properties of the next stimulus (e.g. mean
+ intensity) are adjusted as needed.
+ .
+ RELACS comes with an extensive set of data-analysis functions. The
+ functions are implemented in C++ to allow fast and memory efficient
+ data-analysis as it is required for closed-loop experiments:
+  - Basic statistics (e.g. mean, standard deviation)
+  - Spectral analysis: power spectrum, transfer function, coherence
+  - Linear and nonlinear fits (Levenberg-Marquardt and Simplex)
+  - Peak detection
+  - Histograms, interpolation
+  - Stimulus generation: pulse, saw tooth, band-pass filtered white
+    noise, Ornstein-Uhlenbeck noise
+  - Firing rates: mean, binned, convolved with kernels (e.g. rectangle,
+    triangle, Gaussian)
+  - Interspike intervals: histogram, CV, serial correlation, etc.
+  - Spike timing precision: vector strength, reliability, correlation,
+    synchrony etc.
+ .
+ RELACS plugin infrastructure allows to adapt it to specific hardware
+ drivers and they allow you to implement research protocols, filters,
+ spike detectors, etc.
diff --git a/future/blends/spike b/future/blends/spike
new file mode 100644 (file)
index 0000000..b8b939e
--- /dev/null
@@ -0,0 +1,16 @@
+Source: spike
+Tasks: debian-science/neuroscience-electrophysiology
+
+Language: C++, Octave/Matlab
+License: BSD-3 and Academic Free License
+Responsible: NeuroDebian Team <team@neuro.debian.net>
+Homepage: http://neuroanalysis.org
+Published-Title: Spike Train Analysis Toolkit: Enabling Wider Application of Information-Theoretic Techniques to Neurophysiology
+Published-Authors: David H. Goldberg, Jonathan D. Victor, Esther P. Gardner, and Daniel Gardner
+Published-In: Neuroinformatics, 7, 165–178
+Published-Year: 2009
+Published-DOI: 10.1007/s12021-009-9049-y
+Pkg-Description: spike train analysis toolbox
+ This toolbox implements several information-theoretic spike train analysis
+ techniques. This implementation behaves like a typical MATLAB toolbox, but
+ the underlying computations are coded in C and optimized for efficiency.
diff --git a/future/blends/stimfit b/future/blends/stimfit
new file mode 100644 (file)
index 0000000..84b640f
--- /dev/null
@@ -0,0 +1,19 @@
+Source: stimfit
+Tasks: debian-science/neuroscience-electrophysiology
+Homepage: http://code.google.com/p/stimfit/
+Version: 0.10.0
+Author: Christoph Schmidt-Hieber <c.schmidt-hieber@wibr.ucl.ac.uk>
+License: GPL-2
+Pkg-Description: viewing and analyzing of electrophysiological data
+ Stimfit is a free, fast and simple program for viewing and analyzing
+ electrophysiological data.  It features an embedded Python shell that
+ allows you to extend the program functionality by using numerical
+ libraries such as NumPy and SciPy.
+ .
+ It includes stfio module which supports some electrophysiological
+ file formats:
+  - Read/write: CFS binary data, HDF5 files, Axon text files,
+    ASCII files
+  - Read-only: Axon binary files (*.abf), Axograph files (*.axgd,
+    *.axgx), HEKA files (*.dat, from version 0.10)
+    * Write-only: Igor binary waves (*.ibw)
diff --git a/future/blends/trellis-neuro b/future/blends/trellis-neuro
new file mode 100644 (file)
index 0000000..75c9099
--- /dev/null
@@ -0,0 +1,11 @@
+Source: trellis-neuro
+Tasks: debian-science/neuroscience-electrophysiology
+Homepage: http://sourceforge.net/projects/trellis-neuro/
+License: GPL-3+ and LGPL-3+
+Author: Ripple, LLC
+Language: C, C++
+Pkg-Description: interface to neurophysiology data acquisition and stimulation instruments
+ Trellis-Neuro is an Open Source, multi-platform application suite for
+ interfacing with neurophysiology data acquisition and stimulation
+ instruments. It is based on the eXtensible Instrument Processing
+ Protocol (XIPP), QT 4, and C/C++.
index 11f7572ed6e2ac2753aa8d510b0e03a47109a217..083b1e6fe97b2a1ac29a69fd23741afd3e54d912 100755 (executable)
@@ -19,7 +19,7 @@ Possible TODOs:
 * For every package the same task file might be re-read/written (if
   entry changed/added) from disk.
   That allows to replace easily original entry for 'source' package
-  (listed as Ignore:) with actual first listed binary package.
+  (listed as Suggests:) with actual first listed binary package.
   This should be taken into consideration if current per-package
   handling gets changed
 
@@ -85,7 +85,7 @@ Published-Year: 2008
 Published-DOI: 10.3389/neuro.11.005.2008
 
  ; May be some previous entry should be removed, thus say so
-Removed: python-brian-doc
+Remove: python-brian-doc
 
  ;Tasks: debian-med/imaging-dev
  ;Why: Allows interactive development/scripting
@@ -104,7 +104,7 @@ Removed: python-brian-doc
 """
 
 
-import re, os, sys
+import re, os, sys, tempfile
 from os.path import join, exists, expanduser, dirname, basename
 
 from ConfigParser import ConfigParser
@@ -125,28 +125,37 @@ def open(f, *args):
 
 __author__ = 'Yaroslav Halchenko'
 __prog__ = os.path.basename(sys.argv[0])
-__version__ = '0.0.2'
+__version__ = '0.0.4'
 __copyright__ = 'Copyright (c) 2010 Yaroslav Halchenko'
 __license__ = 'GPL'
 
 # What fields initiate new package description
-PKG_FIELDS = ('depends', 'recommends', 'suggests', 'ignore', 'removed')
+PKG_FIELDS = ('depends', 'recommends', 'suggests', 'ignore', 'remove')
 
 # We might need to resort to assure some what a canonical order
-FIELDS_ORDER = ('depends', 'recommends', 'suggests', 'ignore',
-                'homepage', 'language', 'wnpp', 'responsible', 'license',
+# Prefixes for "standard" blends/tasks fields.  Others do not get embedded
+# into tasks files
+BLENDS_FIELDS_PREFIXES = ('depends', 'recommends', 'suggests', 'ignore',
+                'why', 'homepage', 'language', 'wnpp', 'responsible', 'license',
                 'vcs-', 'pkg-url', 'pkg-description',
                 'published-', 'x-', 'registration', 'remark')
+# Additional fields which might come useful (e.g. for filing wnpp bugs)
+# but are not "standard" thus should be in the trailer
+CUSTOM_FIELDS_PREFIXES = ('author', 'pkg-name', 'pkg-source',
+                          'version', 'remove')
+# Other fields should cause Error for consistency
+
+FIELDS_ORDER = BLENDS_FIELDS_PREFIXES + CUSTOM_FIELDS_PREFIXES
 
 verbosity = None
 
-def error(msg, exit_code):
+def error(msg, exit_code=1):
     sys.stderr.write(msg + '\n')
     sys.exit(exit_code)
 
 def verbose(level, msg):
     if level <= verbosity:
-        print " "*level, msg
+        sys.stderr.write(" "*level + msg + '\n')
 
 
 def parse_debian_blends(f='debian/blends'):
@@ -186,6 +195,7 @@ def parse_debian_blends(f='debian/blends'):
     for k, v in items:
 
         kl = k.lower()
+
         if kl == 'source':
             source = v.strip()
         elif kl == 'format':
@@ -195,7 +205,7 @@ def parse_debian_blends(f='debian/blends'):
                 format_ = format_[:-6]
         elif kl == 'tasks':
             tasks = v.split(',')
-            newtasks = True                 # either we need to provide tune-ups
+            newtasks = pkg is not None      # either we need to provide tune-ups
                                             # for current package
         elif kl in PKG_FIELDS: # new package
             if source is None:
@@ -203,15 +213,17 @@ def parse_debian_blends(f='debian/blends'):
             pkg = new_pkg(pkg, v, source, tasks)
             newtasks = False
         else:
+                       if pkg is None:
+                               # So we had just source?
+                               if source is None:
+                                       error("No package or source is known where to add %s" % (k,), 1)
+                                       # TODO: just deduce source from DebianMaterials
+                               pkg = new_pkg(pkg, source, source, tasks)
+                               # Since only source is available, it should be only Suggest:-ed
+                               pkg['Suggests'] = source
+                               newtasks = False
+
             if newtasks:
-                if pkg is None:
-                    # So we had just source?
-                    if source is None:
-                        error("No package or source is known where to add %s" % k)
-                    pkg = new_pkg(pkg, source, source, tasks)
-                    # Since only source is available, it should be Ignore:-ed
-                    pkg['Ignore'] = source
-                    newtasks = False
                 # Add customization
                 for t in tasks:
                     if not t in pkg.tasks:
@@ -220,6 +232,7 @@ def parse_debian_blends(f='debian/blends'):
             else:
                 # just store the key in the pkg itself
                 pkg[k] = v
+
     return pkgs
 
 
@@ -229,6 +242,7 @@ def expand_pkgs(pkgs, topdir='.'):
     """
     verbose(4, "Expanding content for %d packages" % len(pkgs))
     debianm = None
+
     # Expand packages which format is extended
     for pkg in pkgs:
         if pkg.format == 'extended':
@@ -249,7 +263,24 @@ def expand_pkgs(pkgs, topdir='.'):
             # VCS fields
             pkg.update(debianm.get_vcsfields())
 
-def key_prefix_compare(x, y, order, strict=False, case=False):
+
+def prefix_index(x, entries, strict=True, case=False, default=10000):
+    """Returns an index for the x in entries
+    """
+    if not case:
+        x = x.lower()
+    for i, v in enumerate(entries):
+        if x.startswith(v):
+            return i
+
+    if strict:
+        raise IndexError(
+            "Could not find location for %s as specified by %s" %
+            (x, entries))
+    return default
+
+
+def key_prefix_compare(x, y, order, strict=True, case=False):
     """Little helper to help with sorting
 
     Sorts according to the order of string prefixes as given by
@@ -260,22 +291,8 @@ def key_prefix_compare(x, y, order, strict=False, case=False):
     if not case:
         order = [v.lower() for v in order]
 
-    def prefix_index(t, order, strict=True, case=False):
-        x = t[0]
-        if not case:
-            x = x.lower()
-        for i, v in enumerate(order):
-            if x.startswith(v):
-                return i
-
-        if strict:
-            raise IndexError(
-                "Could not find location for %s as specified by %s" %
-                (x, order))
-        return 10000                    #  some large number ;)
-
-    cmp_res =  cmp(prefix_index(x, order, strict, case),
-                   prefix_index(y, order, strict, case))
+    cmp_res =  cmp(prefix_index(x[0], order, strict, case),
+                   prefix_index(y[0], order, strict, case))
     if not cmp_res:                     # still unknown
         return cmp(x, y)
     return cmp_res
@@ -311,7 +328,12 @@ def group_packages_into_tasks(pkgs):
 
             # Move Pkg-source/name into attributes
             pkg__.source = pkg__.pop('Pkg-Source')
-            pkg__.name = pkg__.pop('Pkg-name')
+            pkg__.name = pkg__.pop('Pkg-Name')
+            # Store the action taken on the package for later on actions
+            for f in PKG_FIELDS:
+                if f in pkg__:
+                    pkg__.action = f
+                    break
 
             tasks[task] = tasks.get(task, []) + [pkg__]
     verbose(4, "Grouped %d packages into %d tasks: %s" %
@@ -329,6 +351,17 @@ def inject_tasks(tasks, config):
         stats = dict(Added=[], Modified=[])
         for pkg in pkgs:
             msgs = {'Name': pkg.name.strip(), 'Action': None}
+
+            # Create a copy of the pkg with only valid tasks
+            # fields:
+            # TODO: make it configurable?
+            pkg = deepcopy(pkg)
+            for k in pkg:
+                if prefix_index(k, BLENDS_FIELDS_PREFIXES,
+                                strict=False, default=None) is None:
+                    pkg.pop(k) # remove it from becoming present in
+                               # the taskfile
+
             # Find either it is known to the task file already
 
             # Load entirely so we could simply manipulate
@@ -349,7 +382,9 @@ def inject_tasks(tasks, config):
 
             descr = ' ; Added by %s %s. [Please note here if modified manually]\n' % \
                     (__prog__,  __version__)
-            # Replace existing entry
+
+            entry = pkg.dump()
+            # Replace existing entry?
             if known:
                 # TODO: Check if previous copy does not have our preceding comment
                 # Find the previous end
@@ -362,33 +397,53 @@ def inject_tasks(tasks, config):
 
                 # Lets not change file without necessity, if entry is identical --
                 # do nothing
-                entry = pkg.dump()
                 old_entry = entries[istart:istart+icount]
 
                 if u''.join(old_entry) == entry:
-                   pass
+                    # no changes -- just go to the next one
+                    continue
                 else: # Rewrite the entry
                    if __prog__ in entries[istart-1]:
                        istart -= 1
                        icount += 2
-                   if not 'Removed' in pkg.keys():
-                       entries = entries[:istart] + [descr + entry] + entries[istart+icount:]
+                   if 'remove' != pkg.action:
+                       entry = descr + entry
                        msgs['Action'] = 'Changed'
                    else:
                        while entries[istart-1].strip() == '':
                            istart -=1
                            icount +=2
-                       entries = entries[:istart] + entries[istart+icount:]
+                       entry = ''
                        msgs['Action'] = 'Removed'
-                   output = ''.join(entries)         # 'compute' first
-                   open(taskfile, 'w').write(output) # then only overwrite
-            elif not 'removed' in pkg:  # or Append one
+                   entries_prior = entries[:istart]
+                   entries_post = entries[istart+icount:]
+            elif not 'remove' == pkg.action:  # or Append one
                 msgs['Action'] = 'Added'
+                entries_prior = entries
+                entry = descr + entry
+                entries_post = []
                 # could be as simple as
-                output = '\n%s%s' % (descr, pkg.dump(),)
-                open(taskfile, 'a').write(output)
+                # Lets do 'in full' for consistent handling of empty lines
+                # around
+                #output = '\n%s%s' % (descr, pkg.dump(),)
+                #open(taskfile, 'a').write(output)
 
             if msgs['Action']:
+                # Prepare for dumping
+                # Prune spaces before
+                while len(entries_prior) and entries_prior[-1].strip() == '':
+                    entries_prior = entries_prior[:-1]
+                if len(entries_prior) and not entries_prior[-1].endswith('\n'):
+                    entries_prior[-1] += '\n' # assure present trailing newline
+                # Prune spaces after
+                while len(entries_post) and entries_post[0].strip() == '':
+                    entries_post = entries_post[1:]
+                if len(entries_post) and len(entry):
+                    # only then trailing empty line
+                    entry += '\n'
+                output = ''.join(entries_prior + [ '\n' + entry ] + entries_post)
+                open(taskfile, 'w').write(output) # then only overwrite
+
                 verbose(3, "%(Action)s %(Name)s" % msgs)
 
 
@@ -501,6 +556,43 @@ class DebianMaterials(object):
                   % (pkg_name, self))
         return self.binaries[pkg_name]['Description']
 
+def print_wnpp(pkgs, config, wnpp_type="ITP"):
+    """Little helper to spit out formatted entry for WNPP bugreport
+
+    TODO: It would puke atm if any field is missing
+    """
+
+    pkg = pkgs[0]                       # everything is based on the 1st one
+    opts = dict(pkg.items())
+    opts['WNPP-Type'] = wnpp_type.upper()
+    opts['Pkg-Description-Short'] = re.sub('\n.*', '', pkg['Pkg-Description'])
+
+    subject = "%(WNPP-Type)s: %(Pkg-Name)s -- %(Pkg-Description-Short)s" % opts
+    body = """*** Please type your report below this line ***
+
+* Package name    : %(Pkg-Name)s
+  Version         : %(Version)s
+  Upstream Author : %(Author)s
+* URL             : %(Homepage)s
+* License         : %(License)s
+  Programming Lang: %(Language)s
+  Description     : %(Pkg-Description)s
+
+""" % opts
+
+    # Unfortunately could not figure out how to set the owner, so I will just print it out
+    if False:
+        tmpfile = tempfile.NamedTemporaryFile()
+        tmpfile.write(body)
+        tmpfile.flush()
+        cmd = "reportbug -b --paranoid --subject='%s' --severity=wishlist --body-file='%s' -o /tmp/o.txt wnpp" \
+              % (subject, tmpfile.name)
+        verbose(2, "Running %s" %cmd)
+        os.system(cmd)
+    else:
+        print "Subject: %s\n\n%s" % (subject, body)
+
+
 def main():
 
     p = OptionParser(
@@ -523,9 +615,24 @@ def main():
         Option("-v", "--verbosity", action="store", type="int",
                dest="verbosity", default=1, help="Noise level."))
 
+    # We might like to create a separate 'group' of options for commands
+    p.add_option(
+        Option("-w", action="store_true",
+               dest="wnpp", default=False,
+               help="Operate in WNPP mode: dumps cut-paste-able entry for WNPP bugreport"))
+
+    p.add_option(
+        Option("--wnpp", action="store",
+               dest="wnpp_mode", default=None,
+               help="Operate in WNPP mode: dumps cut-paste-able entry for WNPP bugreport"))
+
+
     (options, infiles) = p.parse_args()
     global verbosity; verbosity = options.verbosity
 
+       if options.wnpp and options.wnpp_mode is None:
+            options.wnpp_mode = 'ITP'
+
     if not len(infiles):
         infiles = [join(options.topdir or './', 'debian/blends')]     #  default one
 
@@ -546,9 +653,14 @@ def main():
                 topdir = '.'            # and hope for the best ;)
         else:
             topdir = options.topdir
-        expand_pkgs(pkgs, topdir=topdir)
-        tasks = group_packages_into_tasks(pkgs)
-        inject_tasks(tasks, config)
+
+               expand_pkgs(pkgs, topdir=topdir)
+        if options.wnpp_mode is not None:
+                   print_wnpp(pkgs, config, options.wnpp_mode)
+        else:
+            # by default -- operate on blends/tasks files
+            tasks = group_packages_into_tasks(pkgs)
+            inject_tasks(tasks, config)
 
 
 if __name__ == '__main__':