<commit_before>#!/usr/bin/env python
# - coding: utf-8 -

import os
import sys
import re
import gtk
import keybinder
import ConfigParser
import gconf

class GSDesktop_Helper:
  def __init__(self):

    self._NAME    = "GSDesktop Helper"
    self._VERSION = "0.4.2"
    self._AUTHORS = ["Intars Students\nhttp://intarstudents.lv/\n-----", "ppannuto\nhttp://umich.edu/~ppannuto/\n-----", "Icon by Thvg\nhttp://thvg.deviantart.com/"]
    self._INI     = os.path.expanduser('~')+"/.gsdesktop-helper"

    # Try to find icon file
    if os.path.exists("%s/gsd-helper.png" % sys.path[0]):
      self._ICON  = "%s/gsd-helper.png" % sys.path[0]

    elif os.path.exists("/usr/share/pixmaps/gsd-helper.png"):
      self._ICON  = "/usr/share/pixmaps/gsd-helper.png"

    else:
      # Else throw error and exit
      error_msg = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, "Couldn't find icon file!")
      error_msg.run()

      error_msg.destroy()
      os._exit(0)

    # Find shortcutAction.txt file
    self._homedir = "%s/.appdata" % os.path.expanduser('~')
    self._appdata = os.listdir(self._homedir)
    self._shortcutAction = None

    for name in self._appdata:
      m = re.match("^(GroovesharkDesktop[A-Z0-9\.]+)$", name)

      if m:
        self._shortcutAction = "%s/%s/Local Store/shortcutAction.txt" % (self._homedir, m.group(0))

        if os.path.exists(self._shortcutAction):
          break
        else:

          # If shortcutAction.txt doesn't exist try to create it
          try: open(self._shortcutAction, 'w').close()
          except: pass

          if os.path.exists(self._shortcutAction):
            break
          else:
            self._shortcutAction = None

    if not self._shortcutAction:
      error_msg = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, "Couldn't find shortcutAction.txt file!")
      error_msg.run()

      error_msg.destroy()
      os._exit(0)

    # Default list of all hotkeys and their actions
    self._defaults = {
      "next"            : "<Ctrl>period",         # Ctrl + .
      "previous"        : "<Ctrl>comma",          # Ctrl + ,
      "playpause"       : "<Ctrl>equal",          # Ctrl + =
      "shuffle"         : "<Ctrl>grave",          # Ctrl + `
      "radio"           : "<Super>grave",         # Super + `
      "showsongtoast"   : "<Ctrl>slash",          # Ctrl + /
      "togglefavorite"  : "<Ctrl>backslash",      # Ctrl + \
      "togglesmile"     : "<Super>period",        # Super + .
      "togglefrown"     : "<Super>comma",         # Super + ,
      "volumeup"        : "<Ctrl><Alt>Page_Up",   # Ctrl + Alt + Page Up
      "volumedown"      : "<Ctrl><Alt>Page_Down", # Ctrl + Alt + Page Down
    }

    # Load default from default hotkeys
    self._hotkeys = {}
    for toggle in self._defaults:
      self._hotkeys[toggle] = self._defaults[toggle]

    # Nice names for keyboard shortcuts
    self._hotkey_name = [
      ["next"           , "Plays next song"],
      ["previous"       , "Plays previous song"],
      ["playpause"      , "Toggles Play/Pause"],
      ["shuffle"        , "Toggles Shuffle"],
      ["radio"          , "Toggles Radio"],
      ["showsongtoast"  , "Displays song info"],
      ["togglefavorite" , "Favorites song"],
      ["togglesmile"    , "\"Smiles\" song"],
      ["togglefrown"    , "\"Frowns\" song"],
      ["volumeup"       , "Increases volume"],
      ["volumedown"     , "Decreases volume"],
    ]

    self.load_conf()
    self.bindKeys()
    self.protocolHandler()

    # Status icon stuff
    self._status_icon = gtk.StatusIcon()
    self._status_icon.set_from_file(self._ICON)
    self._status_icon.set_tooltip(self._NAME)
    self._status_icon.connect("popup-menu", self.menu_callback)

    gtk.main()

  # Add custom protocol handler
  def protocolHandler(self):
    try:
      self.gconfig = gconf.client_get_default()
      self.gconfig.set_string("/desktop/gnome/url-handlers/gs/command", "%s/Grooveshark %%s" % sys.path[0])
      self.gconfig.set_bool("/desktop/gnome/url-handlers/gs/needs_terminal", False);
      self.gconfig.set_bool("/desktop/gnome/url-handlers/gs/enabled", True);

    except: pass

  # If configuration file exists, load key combos from it
  def load_conf(self):
    try:
      config = ConfigParser.ConfigParser()
      config.read(self._INI)

      for toggle in config.options("hotkeys"):
        if toggle in self._hotkeys.keys():
          self._hotkeys[toggle] = config.get("hotkeys", toggle)

    except: pass

  # If possible, save to configuration file
  def save_conf(self):
    configFile = open(self._INI,"w")

    config = ConfigParser.ConfigParser()
    config.add_section("hotkeys")

    for toggle in self._hotkeys:
      config.set("hotkeys", toggle, self._hotkeys[toggle])

    config.write(configFile)

  def create_conf_window(self):
    # Look and feel of window
    self._window = gtk.Window(gtk.WINDOW_TOPLEVEL)
    self._window.set_title(self._NAME)
    self._window.set_default_size(325, 350)
    self._window.set_icon_from_file(self._ICON)
    self._window.set_position(gtk.WIN_POS_CENTER_ALWAYS)
    self._window.set_border_width(10)

    # Hooks for it (on close and key press)
    self._window.connect("destroy", self.hide_conf_window)
    self._window.connect('key-press-event', self.change_toggle)

    # Currently active input box
    self.modify_toggle = None

    # Windows box handler
    self._confWindowHandler = gtk.VBox(False, 1)
    self._confWindowHandler.show()

    # Build warning box
    warningLabel = gtk.Label()
    warningLabel.set_markup('\nKeyboard shortcuts are disabled, while this window is open.\n');
    warningLabel.show()

    warningBox = gtk.EventBox()
    warningBox.modify_bg(0, gtk.gdk.Color("#AE0000"))
    warningBox.add(warningLabel)
    warningBox.show()

    self._confWindowHandler.pack_end(warningBox, False)

    # Add nice separator
    separator = gtk.HSeparator()
    separator.show()

    self._confWindowHandler.pack_end(separator, False, padding=5)

    # Row handler
    self._confRowBox  = gtk.VBox(False, 0)
    self._confRowBox.show()

    rows = len(self._hotkey_name)
    table = gtk.Table(rows, 3)
    row = 0

    # Allow to edit each toggle
    for toggle, title in self._hotkey_name:
      label = gtk.Label(title)
      label.set_sensitive(self._hotkeys[toggle] != "DISABLED")
      label.set_alignment(0, 0.5)
      label.show()
      table.attach(label, 1, 2, row, row + 1, xpadding=5)

      keyval, state = gtk.accelerator_parse(self._hotkeys[toggle])
      keycombo = gtk.accelerator_get_label(keyval, state)

      # Input box with click event to change active toggle
      entry = gtk.Entry()
      entry.set_editable(False)
      entry.set_text(keycombo)
      entry.set_sensitive(self._hotkeys[toggle] != "DISABLED")
      entry.connect("event", self.focus_toggle, toggle, entry)
      entry.show()
      table.attach(entry, 2, 3, row, row + 1)

      # Checkbutton to enable / disable this hotkey
      # defined out of order w.r.t the table so we can pass label/entry to callback
      checkbutton = gtk.CheckButton()
      checkbutton.set_active(self._hotkeys[toggle] != "DISABLED")
      checkbutton.connect("toggled", self.checkbox_toggle, toggle, label, entry)
      checkbutton.show()

      table.attach(checkbutton, 0, 1, row, row + 1)
      table.set_row_spacing(row, 2)

      row += 1

    table.show()
    self._confRowBox.pack_start(table)

    # To un-clutter windows, if new shortcuts come along, added scrollbar
    self._scrollBox = gtk.ScrolledWindow(hadjustment=None, vadjustment=None)
    self._scrollBox.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
    self._scrollBox.set_shadow_type(gtk.SHADOW_NONE)

    self._scrollBox.add_with_viewport(self._confRowBox)
    self._scrollBox.show()

    # Ok everything is ready, append!
    self._confWindowHandler.pack_start(self._scrollBox)
    self._window.add(self._confWindowHandler)
    self._window.show()

  # Enable / Disable config options
  def checkbox_toggle(self, checkbox, toggle, label, entry):
    if checkbox.get_active():
      label.set_sensitive(True)
      entry.set_sensitive(True)
      self._hotkeys[toggle] = self._defaults[toggle]
      keyval, state = gtk.accelerator_parse(self._hotkeys[toggle])
      keycombo = gtk.accelerator_get_label(keyval, state)
      entry.set_text(keycombo)
      self.save_conf()
    else:
      label.set_sensitive(False)
      entry.set_sensitive(False)
      self._hotkeys[toggle] = "DISABLED"
      self.save_conf()

  # Change toggle (if it isn't same as previous)
  def change_toggle(self, window, event):
    if self.modify_toggle != None:
      entry, toggle = self.modify_toggle

      keyval = event.keyval
      state = event.state
      keycombo = gtk.accelerator_get_label(keyval, state)
      new_toggle = gtk.accelerator_name(keyval, state)

      if not self._hotkeys[toggle] == new_toggle:
        self._hotkeys[toggle] = new_toggle
        entry.set_text(keycombo)
        self.save_conf()

  # Give focus to toggle you want to change
  def focus_toggle(self, widget, event, toggle, entry, data=None):
    if event.type == gtk.gdk.BUTTON_RELEASE:
      self.modify_toggle = (entry, toggle)

  # Create configuration window and unbind keys
  def show_conf_window(self, window):
    self.unbindKeys()
    self.create_conf_window()

  # On window hide bind keys
  def hide_conf_window(self, window):
    self.bindKeys()
    self._window.hide()

  # Handle binding of keys
  def bindKeys(self):
    for toggle in self._hotkeys:
      if not (self._hotkeys[toggle] == "DISABLED"):
        try:  keybinder.unbind(self._hotkeys[toggle])
        except: pass

        # Default bad hotkeys
        if not gtk.accelerator_parse(self._hotkeys[toggle])[0] and not self._hotkeys[toggle] == self._defaults[toggle]:
          self._hotkeys[toggle] = self._defaults[toggle]

        try:
            keybinder.bind(self._hotkeys[toggle], self.keyboard_callback, toggle)

        except: pass

  # Handle unbinding of keys
  def unbindKeys(self):
    for toggle in self._hotkeys:
      if not (self._hotkeys[toggle] == "DISABLED"):
        try:  keybinder.unbind(self._hotkeys[toggle])
        except: pass

  # Handle received hotkey action
  def keyboard_callback(self, toggle):
    if os.path.exists(self._shortcutAction) and os.access(self._shortcutAction, os.W_OK):
      try:
        file = open(self._shortcutAction, "a")
        file.write("%s\n" % toggle)
        file.close()
      except Exception, e:
        print e

  # Handle status icon popup
  def menu_callback(self, icon, button, time):
    menu = gtk.Menu()

    configure   = gtk.MenuItem("Settings")
    about       = gtk.MenuItem("About")
    quit        = gtk.MenuItem("Quit")

    configure.connect("activate", self.show_conf_window)
    about.connect("activate", self.show_about_dialog)
    quit.connect("activate", gtk.main_quit)

    menu.append(configure)
    menu.append(about)
    menu.append(quit)

    menu.show_all()
    menu.popup(None, None, gtk.status_icon_position_menu, button, time, self._status_icon)

  # Show groovy About dialog
  def show_about_dialog(self, widget):

    about_dialog = gtk.AboutDialog()

    about_dialog.set_destroy_with_parent(True)
    about_dialog.set_name(self._NAME)

    about_dialog.set_version(self._VERSION)
    about_dialog.set_authors(self._AUTHORS)
    about_dialog.set_website("http://grooveshark.wikia.com/wiki/GSDesktop_Global_Keyboard_Shortcuts")
    about_dialog.set_website_label("How to groove?")

    icon = gtk.gdk.pixbuf_new_from_file(self._ICON)
    about_dialog.set_logo(icon)

    about_dialog.run()
    about_dialog.destroy()

if __name__ == '__main__':
  GSDesktop_Helper()
<commit_msg>Add actions to status bar menu<commit_after>#!/usr/bin/env python
# - coding: utf-8 -

import os
import sys
import re
import gtk
import keybinder
import ConfigParser
import gconf

class GSDesktop_Helper:
  def __init__(self):

    self._NAME    = "GSDesktop Helper"
    self._VERSION = "0.4.2"
    self._AUTHORS = ["Intars Students\nhttp://intarstudents.lv/\n-----", "ppannuto\nhttp://umich.edu/~ppannuto/\n-----", "Icon by Thvg\nhttp://thvg.deviantart.com/"]
    self._INI     = os.path.expanduser('~')+"/.gsdesktop-helper"

    # Try to find icon file
    if os.path.exists("%s/gsd-helper.png" % sys.path[0]):
      self._ICON  = "%s/gsd-helper.png" % sys.path[0]

    elif os.path.exists("/usr/share/pixmaps/gsd-helper.png"):
      self._ICON  = "/usr/share/pixmaps/gsd-helper.png"

    else:
      # Else throw error and exit
      error_msg = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, "Couldn't find icon file!")
      error_msg.run()

      error_msg.destroy()
      os._exit(0)

    # Find shortcutAction.txt file
    self._homedir = "%s/.appdata" % os.path.expanduser('~')
    self._appdata = os.listdir(self._homedir)
    self._shortcutAction = None

    for name in self._appdata:
      m = re.match("^(GroovesharkDesktop[A-Z0-9\.]+)$", name)

      if m:
        self._shortcutAction = "%s/%s/Local Store/shortcutAction.txt" % (self._homedir, m.group(0))

        if os.path.exists(self._shortcutAction):
          break
        else:

          # If shortcutAction.txt doesn't exist try to create it
          try: open(self._shortcutAction, 'w').close()
          except: pass

          if os.path.exists(self._shortcutAction):
            break
          else:
            self._shortcutAction = None

    if not self._shortcutAction:
      error_msg = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, "Couldn't find shortcutAction.txt file!")
      error_msg.run()

      error_msg.destroy()
      os._exit(0)

    # Default list of all hotkeys and their actions
    self._defaults = {
      "next"            : "<Ctrl>period",         # Ctrl + .
      "previous"        : "<Ctrl>comma",          # Ctrl + ,
      "playpause"       : "<Ctrl>equal",          # Ctrl + =
      "shuffle"         : "<Ctrl>grave",          # Ctrl + `
      "radio"           : "<Super>grave",         # Super + `
      "showsongtoast"   : "<Ctrl>slash",          # Ctrl + /
      "togglefavorite"  : "<Ctrl>backslash",      # Ctrl + \
      "togglesmile"     : "<Super>period",        # Super + .
      "togglefrown"     : "<Super>comma",         # Super + ,
      "volumeup"        : "<Ctrl><Alt>Page_Up",   # Ctrl + Alt + Page Up
      "volumedown"      : "<Ctrl><Alt>Page_Down", # Ctrl + Alt + Page Down
    }

    # Load default from default hotkeys
    self._hotkeys = {}
    for toggle in self._defaults:
      self._hotkeys[toggle] = self._defaults[toggle]

    # Nice names for keyboard shortcuts
    self._hotkey_name = [
      ["next"           , "Plays next song"],
      ["previous"       , "Plays previous song"],
      ["playpause"      , "Toggles Play/Pause"],
      ["shuffle"        , "Toggles Shuffle"],
      ["radio"          , "Toggles Radio"],
      ["showsongtoast"  , "Displays song info"],
      ["togglefavorite" , "Favorites song"],
      ["togglesmile"    , "\"Smiles\" song"],
      ["togglefrown"    , "\"Frowns\" song"],
      ["volumeup"       , "Increases volume"],
      ["volumedown"     , "Decreases volume"],
    ]

    # Nice names for shortcut actions
    self._hotkey_action = [
      ["next"           , "Play next"],
      ["previous"       , "Play previous"],
      ["playpause"      , "Play/Pause"],
      ["shuffle"        , "Shuffle"],
      ["radio"          , "Radio"],
      ["showsongtoast"  , "Show Song Info"],
      ["togglefavorite" , "Favorite Song"],
      ["togglesmile"    , "\"Smile\" Song"],
      ["togglefrown"    , "\"Frown\" Song"],
      ["volumeup"       , "Increase Volume"],
      ["volumedown"     , "Decrease Volume"],
    ]

    self.load_conf()
    self.bindKeys()
    self.protocolHandler()

    # Status icon stuff
    self._status_icon = gtk.StatusIcon()
    self._status_icon.set_from_file(self._ICON)
    self._status_icon.set_tooltip(self._NAME)
    self._status_icon.connect("popup-menu", self.menu_callback)

    gtk.main()

  # Add custom protocol handler
  def protocolHandler(self):
    try:
      self.gconfig = gconf.client_get_default()
      self.gconfig.set_string("/desktop/gnome/url-handlers/gs/command", "%s/Grooveshark %%s" % sys.path[0])
      self.gconfig.set_bool("/desktop/gnome/url-handlers/gs/needs_terminal", False);
      self.gconfig.set_bool("/desktop/gnome/url-handlers/gs/enabled", True);

    except: pass

  # If configuration file exists, load key combos from it
  def load_conf(self):
    try:
      config = ConfigParser.ConfigParser()
      config.read(self._INI)

      for toggle in config.options("hotkeys"):
        if toggle in self._hotkeys.keys():
          self._hotkeys[toggle] = config.get("hotkeys", toggle)

    except: pass

  # If possible, save to configuration file
  def save_conf(self):
    configFile = open(self._INI,"w")

    config = ConfigParser.ConfigParser()
    config.add_section("hotkeys")

    for toggle in self._hotkeys:
      config.set("hotkeys", toggle, self._hotkeys[toggle])

    config.write(configFile)

  def create_conf_window(self):
    # Look and feel of window
    self._window = gtk.Window(gtk.WINDOW_TOPLEVEL)
    self._window.set_title(self._NAME)
    self._window.set_default_size(325, 350)
    self._window.set_icon_from_file(self._ICON)
    self._window.set_position(gtk.WIN_POS_CENTER_ALWAYS)
    self._window.set_border_width(10)

    # Hooks for it (on close and key press)
    self._window.connect("destroy", self.hide_conf_window)
    self._window.connect('key-press-event', self.change_toggle)

    # Currently active input box
    self.modify_toggle = None

    # Windows box handler
    self._confWindowHandler = gtk.VBox(False, 1)
    self._confWindowHandler.show()

    # Build warning box
    warningLabel = gtk.Label()
    warningLabel.set_markup('\nKeyboard shortcuts are disabled, while this window is open.\n');
    warningLabel.show()

    warningBox = gtk.EventBox()
    warningBox.modify_bg(0, gtk.gdk.Color("#AE0000"))
    warningBox.add(warningLabel)
    warningBox.show()

    self._confWindowHandler.pack_end(warningBox, False)

    # Add nice separator
    separator = gtk.HSeparator()
    separator.show()

    self._confWindowHandler.pack_end(separator, False, padding=5)

    # Row handler
    self._confRowBox  = gtk.VBox(False, 0)
    self._confRowBox.show()

    rows = len(self._hotkey_name)
    table = gtk.Table(rows, 3)
    row = 0

    # Allow to edit each toggle
    for toggle, title in self._hotkey_name:
      label = gtk.Label(title)
      label.set_sensitive(self._hotkeys[toggle] != "DISABLED")
      label.set_alignment(0, 0.5)
      label.show()
      table.attach(label, 1, 2, row, row + 1, xpadding=5)

      keyval, state = gtk.accelerator_parse(self._hotkeys[toggle])
      keycombo = gtk.accelerator_get_label(keyval, state)

      # Input box with click event to change active toggle
      entry = gtk.Entry()
      entry.set_editable(False)
      entry.set_text(keycombo)
      entry.set_sensitive(self._hotkeys[toggle] != "DISABLED")
      entry.connect("event", self.focus_toggle, toggle, entry)
      entry.show()
      table.attach(entry, 2, 3, row, row + 1)

      # Checkbutton to enable / disable this hotkey
      # defined out of order w.r.t the table so we can pass label/entry to callback
      checkbutton = gtk.CheckButton()
      checkbutton.set_active(self._hotkeys[toggle] != "DISABLED")
      checkbutton.connect("toggled", self.checkbox_toggle, toggle, label, entry)
      checkbutton.show()

      table.attach(checkbutton, 0, 1, row, row + 1)
      table.set_row_spacing(row, 2)

      row += 1

    table.show()
    self._confRowBox.pack_start(table)

    # To un-clutter windows, if new shortcuts come along, added scrollbar
    self._scrollBox = gtk.ScrolledWindow(hadjustment=None, vadjustment=None)
    self._scrollBox.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
    self._scrollBox.set_shadow_type(gtk.SHADOW_NONE)

    self._scrollBox.add_with_viewport(self._confRowBox)
    self._scrollBox.show()

    # Ok everything is ready, append!
    self._confWindowHandler.pack_start(self._scrollBox)
    self._window.add(self._confWindowHandler)
    self._window.show()

  # Enable / Disable config options
  def checkbox_toggle(self, checkbox, toggle, label, entry):
    if checkbox.get_active():
      label.set_sensitive(True)
      entry.set_sensitive(True)
      self._hotkeys[toggle] = self._defaults[toggle]
      keyval, state = gtk.accelerator_parse(self._hotkeys[toggle])
      keycombo = gtk.accelerator_get_label(keyval, state)
      entry.set_text(keycombo)
      self.save_conf()
    else:
      label.set_sensitive(False)
      entry.set_sensitive(False)
      self._hotkeys[toggle] = "DISABLED"
      self.save_conf()

  # Change toggle (if it isn't same as previous)
  def change_toggle(self, window, event):
    if self.modify_toggle != None:
      entry, toggle = self.modify_toggle

      keyval = event.keyval
      state = event.state
      keycombo = gtk.accelerator_get_label(keyval, state)
      new_toggle = gtk.accelerator_name(keyval, state)

      if not self._hotkeys[toggle] == new_toggle:
        self._hotkeys[toggle] = new_toggle
        entry.set_text(keycombo)
        self.save_conf()

  # Give focus to toggle you want to change
  def focus_toggle(self, widget, event, toggle, entry, data=None):
    if event.type == gtk.gdk.BUTTON_RELEASE:
      self.modify_toggle = (entry, toggle)

  # Create configuration window and unbind keys
  def show_conf_window(self, window):
    self.unbindKeys()
    self.create_conf_window()

  # On window hide bind keys
  def hide_conf_window(self, window):
    self.bindKeys()
    self._window.hide()

  # Handle binding of keys
  def bindKeys(self):
    for toggle in self._hotkeys:
      if not (self._hotkeys[toggle] == "DISABLED"):
        try:  keybinder.unbind(self._hotkeys[toggle])
        except: pass

        # Default bad hotkeys
        if not gtk.accelerator_parse(self._hotkeys[toggle])[0] and not self._hotkeys[toggle] == self._defaults[toggle]:
          self._hotkeys[toggle] = self._defaults[toggle]

        try:
            keybinder.bind(self._hotkeys[toggle], self.keyboard_callback, toggle)

        except: pass

  # Handle unbinding of keys
  def unbindKeys(self):
    for toggle in self._hotkeys:
      if not (self._hotkeys[toggle] == "DISABLED"):
        try:  keybinder.unbind(self._hotkeys[toggle])
        except: pass

  # Handle received hotkey action
  def keyboard_callback(self, toggle):
    if os.path.exists(self._shortcutAction) and os.access(self._shortcutAction, os.W_OK):
      try:
        file = open(self._shortcutAction, "a")
        file.write("%s\n" % toggle)
        file.close()
      except Exception, e:
        print e

  # Handle action from context menu
  def menu_action_callback(self, widget, toggle):
    self.keyboard_callback(toggle)

  # Handle status icon popup
  def menu_callback(self, icon, button, time):
    menu = gtk.Menu()

    configure   = gtk.MenuItem("Settings")
    about       = gtk.MenuItem("About")
    quit        = gtk.MenuItem("Quit")
    separator   = gtk.MenuItem()

    configure.connect("activate", self.show_conf_window)
    about.connect("activate", self.show_about_dialog)
    quit.connect("activate", gtk.main_quit)

    menu.append(configure)
    menu.append(about)
    menu.append(quit)
    menu.append(separator)
    for toggle,action in self._hotkey_action:
      menu_item = gtk.MenuItem(action)
      menu_item.connect("activate", self.menu_action_callback, toggle)
      menu.append(menu_item)

    menu.show_all()
    menu.popup(None, None, gtk.status_icon_position_menu, button, time, self._status_icon)

  # Show groovy About dialog
  def show_about_dialog(self, widget):

    about_dialog = gtk.AboutDialog()

    about_dialog.set_destroy_with_parent(True)
    about_dialog.set_name(self._NAME)

    about_dialog.set_version(self._VERSION)
    about_dialog.set_authors(self._AUTHORS)
    about_dialog.set_website("http://grooveshark.wikia.com/wiki/GSDesktop_Global_Keyboard_Shortcuts")
    about_dialog.set_website_label("How to groove?")

    icon = gtk.gdk.pixbuf_new_from_file(self._ICON)
    about_dialog.set_logo(icon)

    about_dialog.run()
    about_dialog.destroy()

if __name__ == '__main__':
  GSDesktop_Helper()
<|endoftext|>


<commit_before>"""Example using Tom's registration code from scipy.

"""

from os import path
from glob import glob

import numpy as np

import scipy.ndimage._registration as reg

from neuroimaging.core.image import image

# Data files
basedir = '/Users/cburns/data/twaite'
anatfile = path.join(basedir, 'ANAT1_V0001.img')
funcdir = path.join(basedir, 'fMRIData')
fileglob = path.join(funcdir, 'FUNC1_V000?.img')   # Get first 10 images

# Image names proposed:  Run past Matthew Brett
# Reference for the template/anatomical images
# Moving for the functional images

def demo_coregistration(anatfile, funclist, optimizer_method='hybrid',
                        histo_method=1, smooth_histo=0, smooth_image=0,
                        ftype=1):
    """Coregister functional images to the anatomical image.

    Each fMRI volume is first perturbed (rotated, translated) by a random
    value. The initial registration is measured, then the optimal alignment is
    computed and the registration measure made following the volume remap.
    The fMRI registration is done with the first fMRI volume using normalized
    cross-correlation.  Each fMRI volume is rotated to the fMRI-0 volume and
    the series is ensemble averaged.  The ensemble averaged is then registered
    with the anatomical MRI volume using normalized mutual information.
    The fMRI series is then rotated with this parameter. The alignments are
    done with 3D cubic splines.

    Parameters
    ----------
    anatfile : filename
        path to the anatomical file
    funclist : list
        list of paths to functional images
    optimizer_methods : {'powell', 'cg', 'hybrid'}
        default is hybrid which uses powell for the low-res pass (first pass),
        conjugate gradient for the hi-res pass (second pass)
    histo_method :
    smooth_histo :
    smooth_image :
    ftype :

    Returns
    -------
    measures : ndarray
    imageF_anat : dict
    fmri_series : dict

    Notes
    -----
    show results with

    In [59]: measures[25]['cost']
    Out[59]: -0.48607185

    In [60]: measures[25]['align_cost']
    Out[60]: -0.99514639

    In [61]: measures[25]['align_rotate']
    Out[61]:
    array([ 1.94480181,  5.64703989,  5.35002136, -5.00544405, -2.2712214, -1.42249691], dtype=float32)

    In [62]: measures[25]['rotate']
    Out[62]:
    array([ 1.36566341,  4.70644331,  4.68198586, -4.32256889, -2.47607017, -2.39173937], dtype=float32)

    """

    # read the anatomical MRI volume
    anat_desc = reg.load_anatMRI_desc()
    # load_volume returns dict: data as ndarray, layers, rows, cols
    imageF_anat = load_volume(anat_desc, imagename=anatfile)
    # the sampling structure
    # Want smoothing sigmas, and subsample resolution
    imdata = reg.build_structs()
    # the volume filter
    # build_fwhm(affine_voxel_to_mm, subsample_resolution)
    imageF_anat['fwhm'] = reg.build_fwhm(imageF_anat['mat'], imdata['step'])

    # read in the file list of the fMRI data
    # rotate is the simulated/perturbed rotation
    # align_rotate is the rotation params resulting from registration.
    # 6 params are alpha (pitch), beta (roll), gamma (yaw),
    #     xtrans, ytrans, ztrans
    metric_test = np.dtype([('cost', 'f'),
                           ('align_cost', 'f'),
                           ('rotate', 'f', 6),
                           ('align_rotate', 'f', 6)])

    fMRIdata = funclist
    fmri_desc = reg.load_fMRI_desc()
    fmri_series = {}
    ave_fMRI_volume = np.zeros(fmri_desc['layers']*fmri_desc['rows']
                               *fmri_desc['cols'],
                      dtype=np.float64).reshape(fmri_desc['layers'],
                                                fmri_desc['rows'],
                                                fmri_desc['cols'])
    count = 0
    number_volumes = len(fMRIdata)
    measures = np.zeros(number_volumes, dtype=metric_test)
    # load and perturb (rotation, translation) the fMRI volumes
    for i in fMRIdata:
        image = reg.load_volume(fmri_desc, i)
        # random perturbation of angle, translation for each volume beyond
        # the first
        if count == 0:
            image['fwhm'] = reg.build_fwhm(image['mat'], imdata['step'])
            fmri_series[count] = image
            count = count + 1
        else:
            x = np.random.random(6) - 0.5
            x = 10.0 * x
            # demo_rotate_fMRI_volume(dict, float)
            # dict :  fwhm, image dimensions and array
            fmri_series[count] = reg.demo_rotate_fMRI_volume(image, x)
            measures[count]['rotate'][0:6] = x[0:6]
            count = count + 1

    # load and register the fMRI volumes with volume_0 using normalized
    # cross correlation metric
    imageF = fmri_series[0]
    if smooth_image:
        image_F_xyz = reg.filter_image_3D(imageF['data'], imageF['fwhm'], ftype)
        imageF['data'] = image_F_xyz
    for i in range(1, number_volumes):
        imageG = fmri_series[i]
        # the measure prior to alignment
        measures[i]['cost'] = reg.check_alignment(imageF, imageG, imdata,
                                                  method='ncc',
                                                  lite=histo_method,
                                                  smhist=smooth_histo)
        x = reg.python_coreg(imageF, imageG, imdata, lite=histo_method,
                         method='ncc', opt_method=optimizer_method,
                         smhist=smooth_histo, smimage=smooth_image)
        measures[i]['align_rotate'][0:6] = x[0:6]
        measures[i]['align_cost'] = reg.check_alignment(imageF, imageG, imdata,
                                                        method='ncc',
                                                        lite=histo_method,
                                                        smhist=smooth_histo,
                                                        alpha=x[0],
                                                        beta=x[1],
                                                        gamma=x[2],
                                                        Tx=x[3],
                                                        Ty=x[4],
                                                        Tz=x[5])

    # align the volumes and average them for co-registration with the
    # anatomical MRI
    ave_fMRI_volume = fmri_series[0]['data'].astype(np.float64)
    for i in range(1, number_volumes):
        image = fmri_series[i]
        x[0:6] = measures[i]['align_rotate'][0:6]
        # overwrite the fMRI volume with the aligned volume
        fmri_series[i] = reg.remap_image(image, x, resample='cubic')
        ave_fMRI_volume = ave_fMRI_volume + fmri_series[i]['data'].astype(np.float64)

    ave_fMRI_volume = (ave_fMRI_volume / float(number_volumes)).astype(np.uint8)
    ave_fMRI_volume = {'data' : ave_fMRI_volume, 'mat' : imageF['mat'],
                       'dim' : imageF['dim'], 'fwhm' : imageF['fwhm']}
    # register (using normalized mutual information) with the anatomical MRI
    if smooth_image:
        image_F_anat_xyz = reg.filter_image_3D(imageF_anat['data'],
                                           imageF_anat['fwhm'], ftype)
        imageF_anat['data'] = image_F_anat_xyz
    x = reg.python_coreg(imageF_anat, ave_fMRI_volume, imdata,
                         lite=histo_method, method='nmi',
                         opt_method=optimizer_method, smhist=smooth_histo,
                         smimage=smooth_image)
    print 'functional-anatomical align parameters '
    print x
    for i in range(number_volumes):
        image = fmri_series[i]
        # overwrite the fMRI volume with the anatomical-aligned volume
        fmri_series[i] = reg.remap_image(image, x, resample='cubic')

    return measures, imageF_anat, fmri_series

def load_volume(imagedesc, imagename=None, threshold=0.999, debug=0):
    """Load image volume

    image = load_volume(imagedesc, imagename=None, threshold=0.999, debug=0)
    --- OR ---
    image, h, ih, index = load_volume(imagedesc, imagename=None,
    threshold=0.999, debug=0)

    gets an image descriptor and optional filename and returns a
    scaled 8 bit volume. The scaling is designed to make full use of
    the 8 bits (ignoring high amplitude outliers).  The current method
    uses numpy fromfile and will be replaced by neuroimage nifti load.

    Parameters
    ----------
    imagedesc : {dictionary}
        imagedesc is the descriptor of the image to be read.

    imagename : {string} : optional
        name of image file. No name creates a blank image that is used for
        creating a rotated test image or image rescaling.

    threshold : {float} : optional
        this is the threshold for upper cutoff in the 8 bit
        scaling. The volume histogram and integrated histogram is
        computed and the upper amplitude cutoff is where the
        integrated histogram crosses the value set in the threshold.
        setting threshold to 1.0 means the scaling is done over the
        min to max amplitude range.

    debug : {0, 1} : optional
        when debug=1 the method returns the volume histogram, integrated
        histogram and the amplitude index where the provided threshold occured.

    Returns
    -------
    image : {dictionary}
        the volume data assoicated with the filename or a blank volume
        of the same dimensions as specified in imagedesc.

    --- OR --- (if debug = 1)

    image : {dictionary}
        the volume data assoicated with the filename or a blank volume
        of the same dimensions as specified in imagedesc.

    h : {nd_array}
        the volume 1D amplitude histogram

    ih : {nd_array}
        the volume 1D amplitude integrated histogram

    index : {int}
        the amplitude (histogram index) where the integrated histogram
        crosses the 'threshold' provided.

    Examples
    --------

    >>> import numpy as NP
    >>> import _registration as reg
    >>> anat_desc = reg.load_anatMRI_desc()
    >>> image_anat, h, ih, index = reg.load_volume(anat_desc, imagename='ANAT1_V0001.img', debug=1)
    >>> index
    210

    """

    # load MRI or fMRI volume and return an autoscaled 8 bit image.
    # autoscale is using integrated histogram to deal with outlier
    # high amplitude voxels
    if imagename is None:

        # imagename of none means to create a blank image
        ImageVolume = np.zeros(imagedesc['layers']*imagedesc['rows']*imagedesc['cols'],
                        dtype=np.uint16).reshape(imagedesc['layers'], imagedesc['rows'], imagedesc['cols'])
    else:
        ImageVolume = np.fromfile(imagename,
                        dtype=np.uint16).reshape(imagedesc['layers'], imagedesc['rows'], imagedesc['cols']);

    # the mat (voxel to physical) matrix
    M = np.eye(4, dtype=np.float64);
    # for now just the sample size (mm units) in x, y and z
    M[0][0] = imagedesc['sample_x']
    M[1][1] = imagedesc['sample_y']
    M[2][2] = imagedesc['sample_z']
    # dimensions
    D = np.zeros(3, dtype=np.int32);
    # Gaussian kernel - fill in with build_fwhm()
    F = np.zeros(3, dtype=np.float64);
    D[0] = imagedesc['rows']
    D[1] = imagedesc['cols']
    D[2] = imagedesc['layers']

    if imagename == None:
        # no voxels to scale to 8 bits
        ImageVolume = ImageVolume.astype(np.uint8)
        image = {'data' : ImageVolume, 'mat' : M, 'dim' : D, 'fwhm' : F}
        return image

    # 8 bit scale with threshold clip of the volume integrated histogram
    max = ImageVolume.max()
    min = ImageVolume.min()
    ih  = np.zeros(max-min+1, dtype=np.float64);
    h   = np.zeros(max-min+1, dtype=np.float64);
    if threshold <= 0:
        threshold = 0.999
    elif threshold > 1.0:
        threshold = 1.0
    # get the integrated histogram of the volume and get max from
    # the threshold crossing in the integrated histogram
    index  = reg.register_image_threshold(ImageVolume, h, ih, threshold)
    scale  = 255.0 / (index-min)
    # generate the scaled 8 bit image
    images = (scale*(ImageVolume.astype(np.float)-min))
    images[images>255] = 255
    image = {'data' : images.astype(np.uint8), 'mat' : M, 'dim' : D, 'fwhm' : F}
    if debug == 1:
        return image, h, ih, index
    else:
        return image

if __name__ == '__main__':
    print 'Coregister anatomical:\n', anatfile
    print '\nWith these functional images:'
    funclist = glob(fileglob)
    funclist = funclist[0:4]
    for func in funclist:
        print func
    #measures, imageF_anat, fmri_series = \
    #reg.demo_MRI_coregistration(anatfile, funclist[0:4])
    demo_coregistration(anatfile, funclist)

<commit_msg>Checkpoint before adding pynifti code.  Reorganizing the coregistration example.<commit_after>"""Example using Tom's registration code from scipy.

"""

from os import path
from glob import glob

import numpy as np

import scipy.ndimage._registration as reg

from neuroimaging.core.image import image

# Data files
basedir = '/Users/cburns/data/twaite'
anatfile = path.join(basedir, 'ANAT1_V0001.img')
funcdir = path.join(basedir, 'fMRIData')
fileglob = path.join(funcdir, 'FUNC1_V000?.img')   # Get first 10 images

# Image names proposed:  Run past Matthew Brett
# Reference for the template/anatomical images
# Moving for the functional images

def demo_coregistration(anatfile, funclist, optimizer_method='hybrid',
                        histo_method=1, smooth_histo=0, smooth_image=0,
                        ftype=1):
    """Coregister functional images to the anatomical image.

    Each fMRI volume is first perturbed (rotated, translated) by a random
    value. The initial registration is measured, then the optimal alignment is
    computed and the registration measure made following the volume remap.
    The fMRI registration is done with the first fMRI volume using normalized
    cross-correlation.  Each fMRI volume is rotated to the fMRI-0 volume and
    the series is ensemble averaged.  The ensemble averaged is then registered
    with the anatomical MRI volume using normalized mutual information.
    The fMRI series is then rotated with this parameter. The alignments are
    done with 3D cubic splines.

    Parameters
    ----------
    anatfile : filename
        path to the anatomical file
    funclist : list
        list of paths to functional images
    optimizer_methods : {'powell', 'cg', 'hybrid'}
        default is hybrid which uses powell for the low-res pass (first pass),
        conjugate gradient for the hi-res pass (second pass)
    histo_method :
    smooth_histo :
    smooth_image :
    ftype :

    Returns
    -------
    measures : ndarray
    imageF_anat : dict
    fmri_series : dict

    Notes
    -----
    show results with

    In [59]: measures[25]['cost']
    Out[59]: -0.48607185

    In [60]: measures[25]['align_cost']
    Out[60]: -0.99514639

    In [61]: measures[25]['align_rotate']
    Out[61]:
    array([ 1.94480181,  5.64703989,  5.35002136, -5.00544405, -2.2712214, -1.42249691], dtype=float32)

    In [62]: measures[25]['rotate']
    Out[62]:
    array([ 1.36566341,  4.70644331,  4.68198586, -4.32256889, -2.47607017, -2.39173937], dtype=float32)

    """

    # read the anatomical MRI volume
    anat_desc = reg.load_anatMRI_desc()
    # load_volume returns dict: data as ndarray, layers, rows, cols
    imageF_anat = load_volume(anat_desc, imagename=anatfile)
    # the sampling structure
    # Want smoothing sigmas, and subsample resolution
    imdata = reg.build_structs()
    # the volume filter
    # build_fwhm(affine_voxel_to_mm, subsample_resolution)
    imageF_anat['fwhm'] = reg.build_fwhm(imageF_anat['mat'], imdata['step'])

    # read in the file list of the fMRI data
    # rotate is the simulated/perturbed rotation
    # align_rotate is the rotation params resulting from registration.
    # 6 params are alpha (pitch), beta (roll), gamma (yaw),
    #     xtrans, ytrans, ztrans
    metric_test = np.dtype([('cost', 'f'),
                           ('align_cost', 'f'),
                           ('rotate', 'f', 6),
                           ('align_rotate', 'f', 6)])

    fMRIdata = funclist
    fmri_desc = reg.load_fMRI_desc()
    fmri_series = {}
    ave_fMRI_volume = np.zeros(fmri_desc['layers']*fmri_desc['rows']
                               *fmri_desc['cols'],
                      dtype=np.float64).reshape(fmri_desc['layers'],
                                                fmri_desc['rows'],
                                                fmri_desc['cols'])
    count = 0
    number_volumes = len(fMRIdata)
    measures = np.zeros(number_volumes, dtype=metric_test)
    # load and perturb (rotation, translation) the fMRI volumes
    for i in fMRIdata:
        image = reg.load_volume(fmri_desc, i)
        # random perturbation of angle, translation for each volume beyond
        # the first
        if count == 0:
            image['fwhm'] = reg.build_fwhm(image['mat'], imdata['step'])
            fmri_series[count] = image
            count = count + 1
        else:
            x = np.random.random(6) - 0.5
            x = 10.0 * x
            # demo_rotate_fMRI_volume(dict, float)
            # dict :  fwhm, image dimensions and array
            fmri_series[count] = reg.demo_rotate_fMRI_volume(image, x)
            measures[count]['rotate'][0:6] = x[0:6]
            count = count + 1

    # load and register the fMRI volumes with volume_0 using normalized
    # cross correlation metric
    imageF = fmri_series[0]
    if smooth_image:
        image_F_xyz = reg.filter_image_3D(imageF['data'], imageF['fwhm'], ftype)
        imageF['data'] = image_F_xyz
    for i in range(1, number_volumes):
        imageG = fmri_series[i]
        # the measure prior to alignment
        measures[i]['cost'] = reg.check_alignment(imageF, imageG, imdata,
                                                  method='ncc',
                                                  lite=histo_method,
                                                  smhist=smooth_histo)
        x = reg.python_coreg(imageF, imageG, imdata, lite=histo_method,
                         method='ncc', opt_method=optimizer_method,
                         smhist=smooth_histo, smimage=smooth_image)
        measures[i]['align_rotate'][0:6] = x[0:6]
        measures[i]['align_cost'] = reg.check_alignment(imageF, imageG, imdata,
                                                        method='ncc',
                                                        lite=histo_method,
                                                        smhist=smooth_histo,
                                                        alpha=x[0],
                                                        beta=x[1],
                                                        gamma=x[2],
                                                        Tx=x[3],
                                                        Ty=x[4],
                                                        Tz=x[5])

    # align the volumes and average them for co-registration with the
    # anatomical MRI
    ave_fMRI_volume = fmri_series[0]['data'].astype(np.float64)
    for i in range(1, number_volumes):
        image = fmri_series[i]
        x[0:6] = measures[i]['align_rotate'][0:6]
        # overwrite the fMRI volume with the aligned volume
        fmri_series[i] = reg.remap_image(image, x, resample='cubic')
        ave_fMRI_volume = ave_fMRI_volume + fmri_series[i]['data'].astype(np.float64)

    ave_fMRI_volume = (ave_fMRI_volume / float(number_volumes)).astype(np.uint8)
    ave_fMRI_volume = {'data' : ave_fMRI_volume, 'mat' : imageF['mat'],
                       'dim' : imageF['dim'], 'fwhm' : imageF['fwhm']}
    # register (using normalized mutual information) with the anatomical MRI
    if smooth_image:
        image_F_anat_xyz = reg.filter_image_3D(imageF_anat['data'],
                                           imageF_anat['fwhm'], ftype)
        imageF_anat['data'] = image_F_anat_xyz
    x = reg.python_coreg(imageF_anat, ave_fMRI_volume, imdata,
                         lite=histo_method, method='nmi',
                         opt_method=optimizer_method, smhist=smooth_histo,
                         smimage=smooth_image)
    print 'functional-anatomical align parameters '
    print x
    for i in range(number_volumes):
        image = fmri_series[i]
        # overwrite the fMRI volume with the anatomical-aligned volume
        fmri_series[i] = reg.remap_image(image, x, resample='cubic')

    return measures, imageF_anat, fmri_series

def load_volume(filename, threshold=0.999, debug=0):
    """Load and scale an image.

    Load an image from a file and scale the data into 8bit images.
    The scaling is designed to make full use of the 8 bits (ignoring
    high amplitude outliers).

    Parameters
    ----------
    filename : {string}
        Name of the image file.
    threshold : {float} : optional
        This is the threshold for upper cutoff in the 8 bit
        scaling. The volume histogram and integrated histogram are
        computed and the upper amplitude cutoff is where the
        integrated histogram crosses the value set in the threshold.
        Setting threshold to 1.0 means the scaling is done over the
        min to max amplitude range.

    debug : {0, 1} : optional
        when debug=1 the method returns the volume histogram, integrated
        histogram and the amplitude index where the provided threshold occured.

    Returns
    -------
    image : nipy image
        A nipy image object.

    h : {nd_array}, optional
        the volume 1D amplitude histogram

    ih : {nd_array}, optional
        the volume 1D amplitude integrated histogram

    index : {int}, optional
        the amplitude (histogram index) where the integrated histogram
        crosses the 'threshold' provided.

    Examples
    --------
    # Broken!
    >>> image_anat, h, ih, index = load_volume('ANAT1_V0001.img', debug=1)

    Notes
    -----
    Usage:
    image = load_volume(imagedesc, imagename=None, threshold=0.999, debug=0)
    image, h, ih, index = load_volume(imagedesc, imagename=None,
    threshold=0.999, debug=0)

    """

    # load MRI or fMRI volume and return an autoscaled 8 bit image.
    # autoscale is using integrated histogram to deal with outlier
    # high amplitude voxels

    if imagename is None:

    else:
        ImageVolume = np.fromfile(imagename,
                        dtype=np.uint16).reshape(imagedesc['layers'], imagedesc['rows'], imagedesc['cols']);

    img = image.load(filename)
    # BUG: need some way to verify the data is in the zyx order!

    # the mat (voxel to physical) matrix
    M = np.eye(4, dtype=np.float64);
    # for now just the sample size (mm units) in x, y and z
    M[0][0] = imagedesc['sample_x']
    M[1][1] = imagedesc['sample_y']
    M[2][2] = imagedesc['sample_z']
    # dimensions
    D = np.zeros(3, dtype=np.int32);
    # Gaussian kernel - fill in with build_fwhm()
    F = np.zeros(3, dtype=np.float64);
    D[0] = imagedesc['rows']
    D[1] = imagedesc['cols']
    D[2] = imagedesc['layers']

    # 8 bit scale with threshold clip of the volume integrated histogram
    max = np.max(img)
    min = np.min(img)
    ih  = np.zeros(max-min+1, dtype=np.float64);
    h   = np.zeros(max-min+1, dtype=np.float64);
    if threshold <= 0:
        threshold = 0.999
    elif threshold > 1.0:
        threshold = 1.0

    # get the integrated histogram of the volume and get max from
    # the threshold crossing in the integrated histogram

    # __UPDATE__
    index  = reg.register_image_threshold(ImageVolume, h, ih, threshold)
    scale  = 255.0 / (index-min)

    # generate the scaled 8 bit image
    #images = (scale*(ImageVolume.astype(np.float)-min))
    images = scale * (np.asarray(img).astype(np.float) - min)
    images[images>255] = 255

    #image = {'data' : images.astype(np.uint8), 'mat' : M, 'dim' : D, 'fwhm' : F}
    # image -> create new image
    # M -> img.affine
    # D -> img.shape
    # fwhm -> sampling_sizes param
    image = image.fromarray(data, names, grid)

    if debug == 1:
        return image, h, ih, index
    else:
        return image

def emtpy_volume():
    """Placeholder for the code that Tom has in load_volume to create an
    empty volume.  Cleanup later"""
    raise NotImplementedError

    # imagename of none means to create a blank image
    ImageVolume = np.zeros(imagedesc['layers']*imagedesc['rows']*imagedesc['cols'],
                           dtype=np.uint16).reshape(imagedesc['layers'], imagedesc['rows'], imagedesc['cols'])

    if imagename == None:
        # no voxels to scale to 8 bits
        ImageVolume = ImageVolume.astype(np.uint8)
        image = {'data' : ImageVolume, 'mat' : M, 'dim' : D, 'fwhm' : F}
        return image

if __name__ == '__main__':
    print 'Coregister anatomical:\n', anatfile
    print '\nWith these functional images:'
    funclist = glob(fileglob)
    funclist = funclist[0:4]
    for func in funclist:
        print func
    #measures, imageF_anat, fmri_series = \
    #reg.demo_MRI_coregistration(anatfile, funclist[0:4])
    demo_coregistration(anatfile, funclist)

"""
# reshape into zxy order?

ImageVolume = np.fromfile(imagename,
dtype=np.uint16).reshape(imagedesc['layers'], imagedesc['rows'], imagedesc['cols']);

# affine is in img.affine
# the mat (voxel to physical) matrix
M = np.eye(4, dtype=np.float64);
# for now just the sample size (mm units) in x, y and z
M[0][0] = imagedesc['sample_x']
M[1][1] = imagedesc['sample_y']
M[2][2] = imagedesc['sample_z']

# dims are stored in img.shape
# dimensions
D = np.zeros(3, dtype=np.int32);

# Gaussian kernel - fill in with build_fwhm()
F = np.zeros(3, dtype=np.float64);

# xyz order?
D[0] = imagedesc['rows']
D[1] = imagedesc['cols']
D[2] = imagedesc['layers']

"""
<|endoftext|>


<commit_before>"""
Several utilities for experimenting upon utlc datasets
"""
# Standard library imports
import os
from itertools import repeat

# Third-party imports
import numpy
import theano
from pylearn.datasets.utlc import load_ndarray_dataset

# Local imports
from auc import embed

##################################################
# Shortcuts and auxiliary functions
##################################################

floatX = theano.config.floatX

def get_constant(variable):
    """ Little hack to return the python value of a theano shared variable """
    return theano.function([],
                           variable,
                           mode=theano.compile.Mode(linker='py')
                           )()

def sharedX(value, name=None, borrow=False):
    """Transform value into a shared variable of type floatX"""
    return theano.shared(theano._asarray(value, dtype=floatX),
                         name=name,
                         borrow=borrow)

def subdict(d, keys):
    """ Create a subdictionary of d with the keys in keys """
    result = {}
    for key in keys:
        if key in d: result[key] = d[key]
    return result

def safe_update(dict_to, dict_from):
    """
    Like dict_to.update(dict_from), except don't overwrite any keys.
    """
    for key, val in dict(dict_from).iteritems():
        if key in dict_to:
            raise KeyError(key)
        dict_to[key] = val
    return dict_to

def getboth(dict1, dict2, key, default=None):
    """
    Try to retrieve key from dict1 if exists, otherwise try with dict2.
    If the key is not found in any of them, raise an exception.
    """
    try:
        return dict1[key]
    except KeyError:
        if default is None:
            return dict2[key]
        else:
            return dict2.get(key, default)

##################################################
# Datasets and contest facilities
##################################################

def load_data(conf):
    """
    Loads a specified dataset according to the parameters in the dictionary
    """
    expected = ['normalize',
                'normalize_on_the_fly',
                'randomize_valid',
                'randomize_test',
                'transfer']
    print '... loading Dataset'
    data = load_ndarray_dataset(conf['dataset'], **subdict(conf, expected))

    # Allocate shared variables
    def shared_dataset(data_x):
        """Function that loads the dataset into shared variables"""
        if conf.get('normalize', True):
            return sharedX(data_x, borrow=True)
        else:
            return theano.shared(theano._asarray(data_x), borrow=True)

    if conf.get('normalize_on_the_fly', False):
        return data
    else:
        return map(shared_dataset, data)

def create_submission(conf, transform_valid, transform_test = None):
    """
    Create submission files given a configuration dictionary and a
    computation function.

    Note that it always reload the datasets to ensure valid & test
    are not permuted.
    """
    if transform_test is None:
        transform_test = transform_valid

    # Load the dataset, without permuting valid and test
    kwargs = subdict(conf, ['dataset', 'normalize', 'normalize_on_the_fly'])
    kwargs.update(randomize_valid=False, randomize_test=False)
    valid_set, test_set = load_data(kwargs)[1:3]

    # Valid and test representations
    valid_repr = transform_valid(valid_set.get_value(borrow=True))
    test_repr = transform_test(test_set.get_value(borrow=True))

    # If there are too much features, outputs kernel matrices
    if (valid_repr.shape[1] > valid_repr.shape[0]):
        valid_repr = numpy.dot(valid_repr, valid_repr.T)
        test_repr = numpy.dot(test_repr, test_repr.T)

    # Quantitize data
    valid_repr = numpy.floor((valid_repr / valid_repr.max())*999)
    test_repr = numpy.floor((test_repr / test_repr.max())*999)

    # Convert into text info
    valid_text = ''
    test_text = ''

    for i in xrange(valid_repr.shape[0]):
        for j in xrange(valid_repr.shape[1]):
            valid_text += '%s ' % int(valid_repr[i, j])
        valid_text += '\n'
    del valid_repr

    for i in xrange(test_repr.shape[0]):
        for j in xrange(test_repr.shape[1]):
            test_text += '%s ' % int(test_repr[i, j])
        test_text += '\n'
    del test_repr

    # Write it in a .txt file
    submit_dir = conf['savedir']
    if not os.path.exists(submit_dir):
        os.mkdir(submit_dir)
    elif not os.path.isdir(submit_dir):
        raise IOError('savedir %s is not a directory' % submit_dir)

    basename = os.path.join(submit_dir,
                            conf['dataset'] + '_' + conf['expname']
                            )
    valid_file = open(basename + '_valid.prepro', 'w')
    test_file = open(basename + '_final.prepro', 'w')

    valid_file.write(valid_text)
    test_file.write(test_text)

    valid_file.close()
    test_file.close()

    print "... done creating files"

    os.system('zip -j %s %s %s' % (basename + '.zip',
                                   basename + '_valid.prepro',
                                   basename + '_final.prepro'))

    print "... files compressed"

    os.system('rm %s %s' % (basename + '_valid.prepro',
                            basename + '_final.prepro'))

    print "... useless files deleted"

##################################################
# Proxies for representation evaluations
##################################################

def compute_alc(valid_repr, test_repr):
    """
    Returns the ALC of the valid set VS test set
    Note: This proxy won't work in the case of transductive learning
    (This is an assumption) but it seems to be a good proxy in the
    normal case (i.e only train on training set)
    """

    # Concatenate the sets, and give different one hot labels for valid and test
    n_valid = valid_repr.shape[0]
    n_test = test_repr.shape[0]

    _labvalid = numpy.hstack((numpy.ones((n_valid, 1)),
                              numpy.zeros((n_valid, 1))))
    _labtest = numpy.hstack((numpy.zeros((n_test, 1)),
                             numpy.ones((n_test, 1))))

    dataset = numpy.vstack((valid_repr, test_repr))
    label = numpy.vstack((_labvalid, _labtest))

    print '... computing the ALC'
    return embed.score(dataset, label)

def lookup_alc(data, transform):
    valid_repr = transform(data[1].get_value(borrow=True))
    test_repr = transform(data[2].get_value(borrow=True))

    return compute_alc(valid_repr, test_repr)

def filter_labels(train, label):
    """ Filter examples of train for which we have labels """
    # Examples for which any label is set
    condition = label.get_value(borrow=True).any(axis=1)

    # Compress train and label arrays according to condition
    def aux(var):
        return var.get_value(borrow=True).compress(condition, axis=0)

    return (aux(train), aux(label))

##################################################
# Iterator object for blending datasets
##################################################

class BatchIterator(object):
    """
    Builds an iterator object that can be used to go through the minibatches
    of a dataset, with respect to the given proportions in conf
    """
    def __init__(self, dataset, set_proba, batch_size, seed = 300):
        # Local shortcuts for array operations
        flo = numpy.floor
        sub = numpy.subtract
        mul = numpy.multiply
        div = numpy.divide
        mod = numpy.mod

        # Record external parameters
        self.batch_size = batch_size
        self.dataset = dataset

        # Compute maximum number of samples for one loop
        set_sizes = [get_constant(data.shape[0]) for data in dataset]
        set_batch = [float(self.batch_size) for i in xrange(3)]
        set_range = div(mul(set_proba, set_sizes), set_batch)
        set_range = map(int, numpy.ceil(set_range))

        # Upper bounds for each minibatch indexes
        set_limit = numpy.ceil(numpy.divide(set_sizes, set_batch))
        self.limit = map(int, set_limit)

        # Number of rows in the resulting union
        set_tsign = sub(set_limit, flo(div(set_sizes, set_batch)))
        set_tsize = mul(set_tsign, flo(div(set_range, set_limit)))

        l_trun = mul(flo(div(set_range, set_limit)), mod(set_sizes, set_batch))
        l_full = mul(sub(set_range, set_tsize), set_batch)

        self.length = sum(l_full) + sum(l_trun)

        # Random number generation using a permutation
        index_tab = []
        for i in xrange(3):
            index_tab.extend(repeat(i, set_range[i]))

        # Use a deterministic seed
        self.seed = seed
        rng = numpy.random.RandomState(seed=self.seed)
        self.permut = rng.permutation(index_tab)

    def __iter__(self):
        """ Generator function to iterate through all minibatches """
        counter = [0, 0, 0]
        for chosen in self.permut:
            # Retrieve minibatch from chosen set
            index = counter[chosen]
            minibatch = self.dataset[chosen].get_value(borrow=True)[
                index * self.batch_size:(index + 1) * self.batch_size
            ]
            # Increment the related counter
            counter[chosen] = (counter[chosen] + 1) % self.limit[chosen]
            # Return the computed minibatch
            yield minibatch

    def __len__(self):
        """ Return length of the weighted union """
        return self.length

    def by_index(self):
        """ Same generator as __iter__, but yield only the chosen indexes """
        counter = [0, 0, 0]
        for chosen in self.permut:
            index = counter[chosen]
            counter[chosen] = (counter[chosen] + 1) % self.limit[chosen]
            yield chosen, index

    def by_subtensor(self):
        """ Generator function to iterate through all minibatches subtensors """
        counter = [0, 0, 0]
        for chosen in self.permut:
            # Retrieve minibatch from chosen set
            index = counter[chosen]
            minibatch = self.dataset[chosen][
                index * self.batch_size:(index + 1) * self.batch_size
            ]
            # Increment the related counter
            counter[chosen] = (counter[chosen] + 1) % self.limit[chosen]
            # Return the computed minibatch
            yield minibatch

##################################################
# Miscellaneous
##################################################

def blend(dataset, set_proba, **kwargs):
    """
    Randomized blending of datasets in data according to parameters in conf
    """
    iterator = BatchIterator(dataset, set_proba, 1, **kwargs)
    nrow = len(iterator)
    ncol = get_constant(dataset[0].shape[1])
    array = numpy.empty((nrow, ncol), dataset[0].dtype)
    row = 0
    for chosen, index in iterator.by_index():
        array[row] = dataset[chosen].get_value(borrow=True)[index]
        row += 1

    return sharedX(array, borrow=True)

<commit_msg>New save_submission function un utils.py<commit_after>"""
Several utilities for experimenting upon utlc datasets
"""
# Standard library imports
import os
import zipfile
from itertools import repeat
from tempfile import TemporaryFile

# Third-party imports
import numpy
import theano
from pylearn.datasets.utlc import load_ndarray_dataset

# Local imports
from auc import embed

##################################################
# Shortcuts and auxiliary functions
##################################################

floatX = theano.config.floatX

def get_constant(variable):
    """ Little hack to return the python value of a theano shared variable """
    return theano.function([],
                           variable,
                           mode=theano.compile.Mode(linker='py')
                           )()

def sharedX(value, name=None, borrow=False):
    """Transform value into a shared variable of type floatX"""
    return theano.shared(theano._asarray(value, dtype=floatX),
                         name=name,
                         borrow=borrow)

def subdict(d, keys):
    """ Create a subdictionary of d with the keys in keys """
    result = {}
    for key in keys:
        if key in d: result[key] = d[key]
    return result

def safe_update(dict_to, dict_from):
    """
    Like dict_to.update(dict_from), except don't overwrite any keys.
    """
    for key, val in dict(dict_from).iteritems():
        if key in dict_to:
            raise KeyError(key)
        dict_to[key] = val
    return dict_to

def getboth(dict1, dict2, key, default=None):
    """
    Try to retrieve key from dict1 if exists, otherwise try with dict2.
    If the key is not found in any of them, raise an exception.
    """
    try:
        return dict1[key]
    except KeyError:
        if default is None:
            return dict2[key]
        else:
            return dict2.get(key, default)

##################################################
# Datasets and contest facilities
##################################################

def load_data(conf):
    """
    Loads a specified dataset according to the parameters in the dictionary
    """
    expected = ['normalize',
                'normalize_on_the_fly',
                'randomize_valid',
                'randomize_test',
                'transfer']
    print '... loading dataset'
    data = load_ndarray_dataset(conf['dataset'], **subdict(conf, expected))

    # Allocate shared variables
    def shared_dataset(data_x):
        """Function that loads the dataset into shared variables"""
        if conf.get('normalize', True):
            return sharedX(data_x, borrow=True)
        else:
            return theano.shared(theano._asarray(data_x), borrow=True)

    if conf.get('normalize_on_the_fly', False):
        return data
    else:
        return map(shared_dataset, data)

def save_submission(conf, valid_repr, test_repr):
    """
    Create a submission file given a configuration dictionary and a
    representation for valid and test.
    """
    print '... creating zipfile'

    # Ensure the given directory is correct
    submit_dir = conf['savedir']
    if not os.path.exists(submit_dir):
        os.makedirs(submit_dir)
    elif not os.path.isdir(submit_dir):
        raise IOError('savedir %s is not a directory' % submit_dir)

    basename = os.path.join(submit_dir, conf['dataset'] + '_' + conf['expname'])

    # If there are too much features, outputs kernel matrices
    if (valid_repr.shape[1] > valid_repr.shape[0]):
        valid_repr = numpy.dot(valid_repr, valid_repr.T)
        test_repr = numpy.dot(test_repr, test_repr.T)

    # Quantitize data
    valid_repr = numpy.floor((valid_repr / valid_repr.max())*999)
    test_repr = numpy.floor((test_repr / test_repr.max())*999)

    # Store the representations in two temporary files
    valid_file = TemporaryFile()
    test_file = TemporaryFile()

    numpy.savetxt(valid_file, valid_repr, fmt="%.3f")
    numpy.savetxt(test_file, test_repr, fmt="%.3f")

    # Reread those files and put them together in a .zip
    valid_file.seek(0)
    test_file.seek(0)

    submission = zipfile.ZipFile(basename + ".zip", "w",
                                 compression=zipfile.ZIP_DEFLATED)
    submission.writestr(basename + '_valid.prepro', valid_file.read())
    submission.writestr(basename + '_final.prepro', test_file.read())

    submission.close()
    valid_file.close()
    test_file.close()

def create_submission(conf, transform_valid, transform_test=None):
    """
    Create a submission file given a configuration dictionary and a
    computation function.

    Note that it always reload the datasets to ensure valid & test
    are not permuted.
    """
    if transform_test is None:
        transform_test = transform_valid

    # Load the dataset, without permuting valid and test
    kwargs = subdict(conf, ['dataset', 'normalize', 'normalize_on_the_fly'])
    kwargs.update(randomize_valid=False, randomize_test=False)
    valid_set, test_set = load_data(kwargs)[1:3]

    # Valid and test representations
    valid_repr = transform_valid(valid_set.get_value(borrow=True))
    test_repr = transform_test(test_set.get_value(borrow=True))

    # Convert into text info
    save_submission(conf, valid_repr, test_repr)

##################################################
# Proxies for representation evaluations
##################################################

def compute_alc(valid_repr, test_repr):
    """
    Returns the ALC of the valid set VS test set
    Note: This proxy won't work in the case of transductive learning
    (This is an assumption) but it seems to be a good proxy in the
    normal case (i.e only train on training set)
    """

    # Concatenate the sets, and give different one hot labels for valid and test
    n_valid = valid_repr.shape[0]
    n_test = test_repr.shape[0]

    _labvalid = numpy.hstack((numpy.ones((n_valid, 1)),
                              numpy.zeros((n_valid, 1))))
    _labtest = numpy.hstack((numpy.zeros((n_test, 1)),
                             numpy.ones((n_test, 1))))

    dataset = numpy.vstack((valid_repr, test_repr))
    label = numpy.vstack((_labvalid, _labtest))

    print '... computing the ALC'
    return embed.score(dataset, label)

def lookup_alc(data, transform):
    valid_repr = transform(data[1].get_value(borrow=True))
    test_repr = transform(data[2].get_value(borrow=True))

    return compute_alc(valid_repr, test_repr)

def filter_labels(train, label):
    """ Filter examples of train for which we have labels """
    # Examples for which any label is set
    condition = label.get_value(borrow=True).any(axis=1)

    # Compress train and label arrays according to condition
    def aux(var):
        return var.get_value(borrow=True).compress(condition, axis=0)

    return (aux(train), aux(label))

##################################################
# Iterator object for blending datasets
##################################################

class BatchIterator(object):
    """
    Builds an iterator object that can be used to go through the minibatches
    of a dataset, with respect to the given proportions in conf
    """
    def __init__(self, dataset, set_proba, batch_size, seed=300):
        # Local shortcuts for array operations
        flo = numpy.floor
        sub = numpy.subtract
        mul = numpy.multiply
        div = numpy.divide
        mod = numpy.mod

        # Record external parameters
        self.batch_size = batch_size
        self.dataset = dataset

        # Compute maximum number of samples for one loop
        set_sizes = [get_constant(data.shape[0]) for data in dataset]
        set_batch = [float(self.batch_size) for i in xrange(3)]
        set_range = div(mul(set_proba, set_sizes), set_batch)
        set_range = map(int, numpy.ceil(set_range))

        # Upper bounds for each minibatch indexes
        set_limit = numpy.ceil(numpy.divide(set_sizes, set_batch))
        self.limit = map(int, set_limit)

        # Number of rows in the resulting union
        set_tsign = sub(set_limit, flo(div(set_sizes, set_batch)))
        set_tsize = mul(set_tsign, flo(div(set_range, set_limit)))

        l_trun = mul(flo(div(set_range, set_limit)), mod(set_sizes, set_batch))
        l_full = mul(sub(set_range, set_tsize), set_batch)

        self.length = sum(l_full) + sum(l_trun)

        # Random number generation using a permutation
        index_tab = []
        for i in xrange(3):
            index_tab.extend(repeat(i, set_range[i]))

        # Use a deterministic seed
        self.seed = seed
        rng = numpy.random.RandomState(seed=self.seed)
        self.permut = rng.permutation(index_tab)

    def __iter__(self):
        """ Generator function to iterate through all minibatches """
        counter = [0, 0, 0]
        for chosen in self.permut:
            # Retrieve minibatch from chosen set
            index = counter[chosen]
            minibatch = self.dataset[chosen].get_value(borrow=True)[
                index * self.batch_size:(index + 1) * self.batch_size
            ]
            # Increment the related counter
            counter[chosen] = (counter[chosen] + 1) % self.limit[chosen]
            # Return the computed minibatch
            yield minibatch

    def __len__(self):
        """ Return length of the weighted union """
        return self.length

    def by_index(self):
        """ Same generator as __iter__, but yield only the chosen indexes """
        counter = [0, 0, 0]
        for chosen in self.permut:
            index = counter[chosen]
            counter[chosen] = (counter[chosen] + 1) % self.limit[chosen]
            yield chosen, index

    def by_subtensor(self):
        """ Generator function to iterate through all minibatches subtensors """
        counter = [0, 0, 0]
        for chosen in self.permut:
            # Retrieve minibatch from chosen set
            index = counter[chosen]
            minibatch = self.dataset[chosen][
                index * self.batch_size:(index + 1) * self.batch_size
            ]
            # Increment the related counter
            counter[chosen] = (counter[chosen] + 1) % self.limit[chosen]
            # Return the computed minibatch
            yield minibatch

##################################################
# Miscellaneous
##################################################

def blend(dataset, set_proba, **kwargs):
    """
    Randomized blending of datasets in data according to parameters in conf
    """
    iterator = BatchIterator(dataset, set_proba, 1, **kwargs)
    nrow = len(iterator)
    ncol = get_constant(dataset[0].shape[1])
    array = numpy.empty((nrow, ncol), dataset[0].dtype)
    row = 0
    for chosen, index in iterator.by_index():
        array[row] = dataset[chosen].get_value(borrow=True)[index]
        row += 1

    return sharedX(array, borrow=True)

<|endoftext|>


<commit_before># FMSPy - Copyright (c) 2009 Andrey Smirnov.
#
# See COPYRIGHT for details.

"""
Application factory.

Loading application, dispatching control.
"""

from twisted.plugin import getPlugins
from twisted.python import log
from twisted.internet import defer

from fmspy.application.interfaces import IApplication
import fmspy.plugins

class ApplicationNotFoundError(Exception):
    """
    Application not found in factory.
    """

class ApplicationFactory(object):
    """
    Application factory holds all loaded applications.

    Factory can dispatch calls to applications.

    @ivar apps: loaded applications
    @type apps: C{dict}
    @ivar plugin_module: root module for application plugins
    @type plugin_module: C{module}
    """

    def __init__(self, plugin_module=None):
        """
        Construct factory.

        @param plugin_module: root module for application plugins, defaults to L{fmspy.plugins}.
        @type plugin_module: C{module}
        """
        self.plugin_module = plugin_module
        if self.plugin_module is None:
            self.plugin_module = fmspy.plugins
        self.apps = {}

    @defer.inlineCallbacks
    def load_applications(self):
        """
        Load all applications.

        @return: Deferred, fired on application load complete
        @rtype: C{Deferred}
        """
        for app in getPlugins(IApplication, self.plugin_module):
            if app.enabled():
                log.msg("Loading %r..." % app)
                yield app.load()
                assert app.name() not in self.apps
                self.apps[app.name()] = app

    def get_application(self, name):
        """
        Get application by name.

        @param name: application name
        @type name: C{str}
        @return: application
        @rtype: L{Application}
        """
        if name not in self.apps:
            raise ApplicationNotFoundError, name

        return self.apps[name]

factory = ApplicationFactory()

<commit_msg>Improve error handling and reporting during application load.<commit_after># FMSPy - Copyright (c) 2009 Andrey Smirnov.
#
# See COPYRIGHT for details.

"""
Application factory.

Loading application, dispatching control.
"""

from twisted.plugin import getPlugins
from twisted.python import log
from twisted.internet import defer

from fmspy.application.interfaces import IApplication
import fmspy.plugins

class ApplicationNotFoundError(Exception):
    """
    Application not found in factory.
    """

class ApplicationFactory(object):
    """
    Application factory holds all loaded applications.

    Factory can dispatch calls to applications.

    @ivar apps: loaded applications
    @type apps: C{dict}
    @ivar plugin_module: root module for application plugins
    @type plugin_module: C{module}
    """

    def __init__(self, plugin_module=None):
        """
        Construct factory.

        @param plugin_module: root module for application plugins, defaults to L{fmspy.plugins}.
        @type plugin_module: C{module}
        """
        self.plugin_module = plugin_module
        if self.plugin_module is None:
            self.plugin_module = fmspy.plugins
        self.apps = {}

    @defer.inlineCallbacks
    def load_applications(self):
        """
        Load all applications.

        @return: Deferred, fired on application load complete
        @rtype: C{Deferred}
        """
        for app in getPlugins(IApplication, self.plugin_module):
            if app.enabled():
                log.msg("Loading %r..." % app)
                try:
                    yield app.load()
                    assert app.name() not in self.apps
                except:
                    log.err(None, "Failed loading %r:" % app)
                    continue
                self.apps[app.name()] = app

                log.msg("Loaded %r @ %r." % (app, app.name()))

    def get_application(self, name):
        """
        Get application by name.

        @param name: application name
        @type name: C{str}
        @return: application
        @rtype: L{Application}
        """
        if name not in self.apps:
            raise ApplicationNotFoundError, name

        return self.apps[name]

factory = ApplicationFactory()

<|endoftext|>


<commit_before>import dbmodule
from dbmodule import *

class Helper:

  def __init__(self,args="",commnad=""):
    self.args = args
    self.commnad = commnad

  #process the commnads
  def process(self):
    if self.commnad == "search":
      if not self.args:
        dbmodule.lastresults = dbmodule.searchAll()
        self.printlastResult()
      else:
        dbmodule.lastresults = dbmodule.searchByCriterial(**self.__searchparams())
        self.printlastResult()
    elif self.commnad == "addfav":
      dbmodule.createFavorite(**self.__addfavparams())
    elif self.commnad == "modfav":
      dbmodule.updateFavorite(**self.__modfavparams())
    elif self.commnad == "delfav":
      dbmodule.deleteFavorite(**self.__delfavparams())
    elif self.commnad == "showfav":
      if not self.args:
        dbmodule.lastresults = dbmodule.getFavorites()
        self.printlastResult(True)
      else:
        dbmodule.lastresults = dbmodule.getFavorites(**self.__showfavparams())
        self.printlastResult(True)
    else:
      print "Error"

  # Display the last results
  def printlastResult(self,fav=False):
    if fav:
      print("\033[1;32m*** {0:40} {1:40}\033[0m".format(*["Name","Ranking"]))
      for key,value in dbmodule.lastresults.items():
        print("\033[1;32m[+] {0:40} {1:35}\033[0m".format(*[value["name"],value["ranking"]]))
    else:
      print("\033[1;32m*** {0:40} {1:40}\033[0m".format(*["Name","Author"]))
      for key,value in dbmodule.lastresults.items():
        print("\033[1;32m[+] {0:40} {1:35}\033[0m".format(*[value["name"],value["author"]]))

  # Display the documentation per script
  def displayDoc(self):
    scriptFile = open(dbmodule.scriptsPath+self.args,'r')
    lines = scriptFile.read().splitlines()
    for line in lines:
      if line.startswith("license"):
        break
      print('\033[1;96m'+line+'\033[0m')
    scriptFile.close()

  # used for the autocomplete
  def resultitems(self):
    i = 0
    items = []
    for k,v in dbmodule.lastresults.items():
      items.insert(i,v["name"])
      i = i + 1
    return items

  # private function to set params for search command
  def __searchparams(self):
    if self.args.find('name:') != -1 or self.args.find('category:') != -1 or self.args.find('author:') != -1:
      return self.__setParams()

  #private funtion to set params for addfav command
  def __addfavparams(self):
    if self.args.find('name:') != -1 or self.args.find('ranking:') != -1:
      return self.__setParams()

  #private funtion to set params for delfav command
  def __delfavparams(self):
    if self.args.find('name:') != -1:
      return self.__setParams()

  #private function to set params for modfav command
  def __modfavparams(self):
    if self.args.find('name:') != -1 or self.args.find('newname:') != -1 or self.args.find('newranking:') != -1:
      return self.__setParams()

  #private function to set paramas for showfav command
  def __showfavparams(self):
    if self.args.find('name:') != -1 or self.args.find('ranking:') != -1:
      return self.__setParams()

  # Set Params validations
  def __setParams(self):
    argsdic = {}
    if len(self.args.split(":")) >= 4:
      argsdic.update({
        self.args.split(":")[0]:self.args.split(":")[1].split(" ")[0],
        self.args.split(":")[1].split(" ")[1]:self.args.split(":")[2].split(" ")[0],
        self.args.split(":")[2].split(" ")[1]:self.args.split(":")[3].split(" ")[0]})
    elif len(self.args.split(":")) == 3:
      argsdic.update({
        self.args.split(":")[0]:self.args.split(":")[1].split(" ")[0],
        self.args.split(":")[1].split(" ")[1]:self.args.split(":")[2].split(" ")[0]})
    elif len(self.args.split(":")) == 2:
      argsdic.update({self.args.split(":")[0]:self.args.split(":")[1].split(" ")[0]})
    else:
      print "Plase enter a correct commands"
    return argsdic<commit_msg>Fixing error, using search command with bad params<commit_after>import dbmodule
from dbmodule import *

class Helper:

  def __init__(self,args="",commnad=""):
    self.args = args
    self.commnad = commnad

  #process the commnads
  def process(self):
    if self.commnad == "search":
      if not self.args:
        dbmodule.lastresults = dbmodule.searchAll()
        self.printlastResult()
      elif not self.__searchparams():
        print "Type <<help search>> to see the help menu"
      else:
        dbmodule.lastresults = dbmodule.searchByCriterial(**self.__searchparams())
        self.printlastResult()
    elif self.commnad == "addfav":
      dbmodule.createFavorite(**self.__addfavparams())
    elif self.commnad == "modfav":
      dbmodule.updateFavorite(**self.__modfavparams())
    elif self.commnad == "delfav":
      dbmodule.deleteFavorite(**self.__delfavparams())
    elif self.commnad == "showfav":
      if not self.args:
        dbmodule.lastresults = dbmodule.getFavorites()
        self.printlastResult(True)
      else:
        dbmodule.lastresults = dbmodule.getFavorites(**self.__showfavparams())
        self.printlastResult(True)
    else:
      print "Error"

  # Display the last results
  def printlastResult(self,fav=False):
    if fav:
      print("\033[1;32m*** {0:40} {1:40}\033[0m".format(*["Name","Ranking"]))
      for key,value in dbmodule.lastresults.items():
        print("\033[1;32m[+] {0:40} {1:35}\033[0m".format(*[value["name"],value["ranking"]]))
    else:
      print("\033[1;32m*** {0:40} {1:40}\033[0m".format(*["Name","Author"]))
      for key,value in dbmodule.lastresults.items():
        print("\033[1;32m[+] {0:40} {1:35}\033[0m".format(*[value["name"],value["author"]]))

  # Display the documentation per script
  def displayDoc(self):
    scriptFile = open(dbmodule.scriptsPath+self.args,'r')
    lines = scriptFile.read().splitlines()
    for line in lines:
      if line.startswith("license"):
        break
      print('\033[1;96m'+line+'\033[0m')
    scriptFile.close()

  # used for the autocomplete
  def resultitems(self):
    i = 0
    items = []
    for k,v in dbmodule.lastresults.items():
      items.insert(i,v["name"])
      i = i + 1
    return items

  # private function to set params for search command
  def __searchparams(self):
    if self.args.find('name:') != -1 or self.args.find('category:') != -1 or self.args.find('author:') != -1:
      return self.__setParams()
    else:
      return False
  #private funtion to set params for addfav command
  def __addfavparams(self):
    if self.args.find('name:') != -1 or self.args.find('ranking:') != -1:
      return self.__setParams()

  #private funtion to set params for delfav command
  def __delfavparams(self):
    if self.args.find('name:') != -1:
      return self.__setParams()

  #private function to set params for modfav command
  def __modfavparams(self):
    if self.args.find('name:') != -1 or self.args.find('newname:') != -1 or self.args.find('newranking:') != -1:
      return self.__setParams()

  #private function to set paramas for showfav command
  def __showfavparams(self):
    if self.args.find('name:') != -1 or self.args.find('ranking:') != -1:
      return self.__setParams()

  # Set Params validations
  def __setParams(self):
    argsdic = {}
    if len(self.args.split(":")) >= 4:
      argsdic.update({
        self.args.split(":")[0]:self.args.split(":")[1].split(" ")[0],
        self.args.split(":")[1].split(" ")[1]:self.args.split(":")[2].split(" ")[0],
        self.args.split(":")[2].split(" ")[1]:self.args.split(":")[3].split(" ")[0]})
    elif len(self.args.split(":")) == 3:
      argsdic.update({
        self.args.split(":")[0]:self.args.split(":")[1].split(" ")[0],
        self.args.split(":")[1].split(" ")[1]:self.args.split(":")[2].split(" ")[0]})
    elif len(self.args.split(":")) == 2:
      argsdic.update({self.args.split(":")[0]:self.args.split(":")[1].split(" ")[0]})
    else:
      print "Plase enter a correct commands"
    return argsdic<|endoftext|>


<commit_before>import xml.etree.ElementTree as ET
from abc import ABC

from shapely.affinity import scale

from c3nav.mapdata.utils.misc import get_render_dimensions

class SVGGroup:
    def __init__(self, width: int, height: int, scale: float=1):
        self.width = width
        self.height = height
        self.scale = scale
        self.g = ET.Element('g', {
            'transform': 'scale(1 -1) translate(0 -%d)' % (self.height*scale),
        })

    def get_element(self):
        return self.g

    def get_xml(self):
        return ET.tostring(self.get_element()).decode()

    def add_group(self):
        group = SVGGroup(self.width, self.height, self.scale)
        self.g.append(group)
        return group

class SVGImage(SVGGroup):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.defs = ET.Element('defs')
        self.def_i = 0

        # blur_filter = ET.Element('filter', {'id': 'wallblur'})
        # blur_filter.append(ET.Element('feGaussianBlur', {'in': 'SourceGraphic', 'stdDeviation': str(5*self.scale)}))
        # self.defs.append(blur_filter)

    def get_element(self):
        root = ET.Element('svg', {
            'width': str(self.width*self.scale),
            'height': str(self.height*self.scale),
            'xmlns:svg': 'http://www.w3.org/2000/svg',
            'xmlns': 'http://www.w3.org/2000/svg',
            'xmlns:xlink': 'http://www.w3.org/1999/xlink',
        })
        root.append(self.defs)
        root.append(self.g)
        return root

    def new_defid(self):
        defid = 's'+str(self.def_i)
        self.def_i += 1
        return defid

    def add_geometry(self, geometry, defid=None, comment=None):
        if defid is None:
            defid = self.new_defid()

        scaled = scale(geometry, xfact=self.scale, yfact=self.scale, origin=(0, 0))
        element = ET.fromstring(scaled.svg(0, '#FFFFFF'))
        if element.tag != 'g':
            new_element = ET.Element('g')
            new_element.append(element)
            element = new_element

        paths = element.findall('polyline')
        if len(paths) == 0:
            paths = element.findall('path')

        for path in paths:
            path.attrib.pop('opacity', None)
            path.attrib.pop('fill', None)
            path.attrib.pop('fill-rule', None)
            path.attrib.pop('stroke', None)
            path.attrib.pop('stroke-width', None)

        element.set('id', defid)
        self.defs.append(element)
        return defid

    def add_mask(self, *geometries, inverted=False, defid=None):
        if defid is None:
            defid = self.new_defid()

        mask = ET.Element('mask', {'id': defid})
        mask.append(ET.Element('rect', {'width': '100%', 'height': '100%', 'fill': 'white' if inverted else 'black'}))
        for geometry in geometries:
            mask.append(ET.Element('use', {'xlink:href': '#'+geometry, 'fill': 'black' if inverted else 'white'}))
        self.defs.append(mask)
        return defid

    def add_union(self, *geometries, wall_shadow=False, defid=None):
        if defid is None:
            defid = self.new_defid()

        element = ET.Element('g', {'id': defid})
        for geometry in geometries:
            newelem = ET.Element('use', {'xlink:href': '#'+geometry})
            if wall_shadow:
                newelem.set('filter', 'url(#wallshadow)')
            element.append(newelem)
        self.defs.append(element)
        return defid

    def add_intersection(self, geometry1, geometry2, defid=None):
        if defid is None:
            defid = self.new_defid()

        mask = ET.Element('mask', {'id': defid+'-mask'})
        mask.append(ET.Element('rect', {'width': '100%', 'height': '100%', 'fill': 'black'}))
        mask.append(ET.Element('use', {'xlink:href': '#'+geometry2, 'fill': 'white'}))
        self.defs.append(mask)

        element = ET.Element('g', {'id': defid, 'mask': 'url(#'+defid+'-mask)'})
        element.append(ET.Element('use', {'xlink:href': '#'+geometry1}))
        self.defs.append(element)
        return defid

    def add_difference(self, geometry1, geometry2, defid=None):
        if defid is None:
            defid = self.new_defid()

        mask = ET.Element('mask', {'id': defid+'-mask'})
        mask.append(ET.Element('rect', {'width': '100%', 'height': '100%', 'fill': 'white'}))
        mask.append(ET.Element('use', {'xlink:href': '#'+geometry2, 'fill': 'black'}))
        self.defs.append(mask)

        element = ET.Element('g', {'id': defid, 'mask': 'url(#'+defid+'-mask)'})
        element.append(ET.Element('use', {'xlink:href': '#' + geometry1}))
        self.defs.append(element)
        return defid

    def use_geometry(self, geometry, fill_color=None, fill_opacity=None, opacity=None, mask=None, filter=None,
                     stroke_width=0.0, stroke_color=None, stroke_opacity=None, stroke_linejoin=None):
        element = ET.Element('use', {'xlink:href': '#'+geometry})
        element.set('fill', fill_color or 'none')
        if fill_opacity:
            element.set('fill-opacity', str(fill_opacity))
        if stroke_width:
            element.set('stroke-width', str(stroke_width * self.scale))
        if stroke_color:
            element.set('stroke', stroke_color)
        if stroke_opacity:
            element.set('stroke-opacity', str(stroke_opacity))
        if stroke_linejoin:
            element.set('stroke-linejoin', str(stroke_linejoin))
        if opacity:
            element.set('opacity', str(opacity))
        if mask:
            element.set('mask', 'url(#'+mask+')')
        if filter:
            element.set('filter', 'url(#'+filter+')')

        self.g.append(element)
        return element
<commit_msg>svg.add_geometry() trim everything to two decimal places<commit_after>import re
import xml.etree.ElementTree as ET
from abc import ABC

from shapely.affinity import scale

from c3nav.mapdata.utils.misc import get_render_dimensions

class SVGGroup:
    def __init__(self, width: int, height: int, scale: float=1):
        self.width = width
        self.height = height
        self.scale = scale
        self.g = ET.Element('g', {
            'transform': 'scale(1 -1) translate(0 -%d)' % (self.height*scale),
        })

    def get_element(self):
        return self.g

    def get_xml(self):
        return ET.tostring(self.get_element()).decode()

    def add_group(self):
        group = SVGGroup(self.width, self.height, self.scale)
        self.g.append(group)
        return group

class SVGImage(SVGGroup):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.defs = ET.Element('defs')
        self.def_i = 0

        # blur_filter = ET.Element('filter', {'id': 'wallblur'})
        # blur_filter.append(ET.Element('feGaussianBlur', {'in': 'SourceGraphic', 'stdDeviation': str(5*self.scale)}))
        # self.defs.append(blur_filter)

    def get_element(self):
        root = ET.Element('svg', {
            'width': str(self.width*self.scale),
            'height': str(self.height*self.scale),
            'xmlns:svg': 'http://www.w3.org/2000/svg',
            'xmlns': 'http://www.w3.org/2000/svg',
            'xmlns:xlink': 'http://www.w3.org/1999/xlink',
        })
        root.append(self.defs)
        root.append(self.g)
        return root

    def new_defid(self):
        defid = 's'+str(self.def_i)
        self.def_i += 1
        return defid

    def add_geometry(self, geometry, defid=None, comment=None):
        if defid is None:
            defid = self.new_defid()

        scaled = scale(geometry, xfact=self.scale, yfact=self.scale, origin=(0, 0))
        re_string = re.sub(r'([0-9]+)\.0', r'\1', re.sub(r'([0-9]+\.[0-9])[0-9]+', r'\1', scaled.svg(0, '#FFFFFF')))
        element = ET.fromstring(re_string)
        if element.tag != 'g':
            new_element = ET.Element('g')
            new_element.append(element)
            element = new_element

        paths = element.findall('polyline')
        if len(paths) == 0:
            paths = element.findall('path')

        for path in paths:
            path.attrib.pop('opacity', None)
            path.attrib.pop('fill', None)
            path.attrib.pop('fill-rule', None)
            path.attrib.pop('stroke', None)
            path.attrib.pop('stroke-width', None)

        element.set('id', defid)
        self.defs.append(element)
        return defid

    def add_mask(self, *geometries, inverted=False, defid=None):
        if defid is None:
            defid = self.new_defid()

        mask = ET.Element('mask', {'id': defid})
        mask.append(ET.Element('rect', {'width': '100%', 'height': '100%', 'fill': 'white' if inverted else 'black'}))
        for geometry in geometries:
            mask.append(ET.Element('use', {'xlink:href': '#'+geometry, 'fill': 'black' if inverted else 'white'}))
        self.defs.append(mask)
        return defid

    def add_union(self, *geometries, wall_shadow=False, defid=None):
        if defid is None:
            defid = self.new_defid()

        element = ET.Element('g', {'id': defid})
        for geometry in geometries:
            newelem = ET.Element('use', {'xlink:href': '#'+geometry})
            if wall_shadow:
                newelem.set('filter', 'url(#wallshadow)')
            element.append(newelem)
        self.defs.append(element)
        return defid

    def add_intersection(self, geometry1, geometry2, defid=None):
        if defid is None:
            defid = self.new_defid()

        mask = ET.Element('mask', {'id': defid+'-mask'})
        mask.append(ET.Element('rect', {'width': '100%', 'height': '100%', 'fill': 'black'}))
        mask.append(ET.Element('use', {'xlink:href': '#'+geometry2, 'fill': 'white'}))
        self.defs.append(mask)

        element = ET.Element('g', {'id': defid, 'mask': 'url(#'+defid+'-mask)'})
        element.append(ET.Element('use', {'xlink:href': '#'+geometry1}))
        self.defs.append(element)
        return defid

    def add_difference(self, geometry1, geometry2, defid=None):
        if defid is None:
            defid = self.new_defid()

        mask = ET.Element('mask', {'id': defid+'-mask'})
        mask.append(ET.Element('rect', {'width': '100%', 'height': '100%', 'fill': 'white'}))
        mask.append(ET.Element('use', {'xlink:href': '#'+geometry2, 'fill': 'black'}))
        self.defs.append(mask)

        element = ET.Element('g', {'id': defid, 'mask': 'url(#'+defid+'-mask)'})
        element.append(ET.Element('use', {'xlink:href': '#' + geometry1}))
        self.defs.append(element)
        return defid

    def use_geometry(self, geometry, fill_color=None, fill_opacity=None, opacity=None, mask=None, filter=None,
                     stroke_width=0.0, stroke_color=None, stroke_opacity=None, stroke_linejoin=None):
        element = ET.Element('use', {'xlink:href': '#'+geometry})
        element.set('fill', fill_color or 'none')
        if fill_opacity:
            element.set('fill-opacity', str(fill_opacity))
        if stroke_width:
            element.set('stroke-width', str(stroke_width * self.scale))
        if stroke_color:
            element.set('stroke', stroke_color)
        if stroke_opacity:
            element.set('stroke-opacity', str(stroke_opacity))
        if stroke_linejoin:
            element.set('stroke-linejoin', str(stroke_linejoin))
        if opacity:
            element.set('opacity', str(opacity))
        if mask:
            element.set('mask', 'url(#'+mask+')')
        if filter:
            element.set('filter', 'url(#'+filter+')')

        self.g.append(element)
        return element
<|endoftext|>