| I l@ve RuBoard |
18.7 PyCalc: A Calculator Program/ObjectTo wrap up this chapter, I'm going to show you a practical application for some of the parsing technology introduced in the previous section. This section presents PyCalc -- a Python calculator program with a graphical interface similar to the calculator programs available on most window systems. But like most of the GUI examples in this book, PyCalc offers a few advantages over existing calculators. Because PyCalc is written in Python, it is both easily customized and widely portable across window platforms. And because it is implemented with classes, it is both a standalone program and a reusable object library. 18.7.1 A Simple Calculator GUIBefore I show you how to write a full-blown calculator, though, the module shown in Example 18-13 starts this discussion in simpler terms. It implements a limited calculator GUI, whose buttons just add text to the input field at the top, to compose a Python expression string. Fetching and running the string all at once produces results. Figure 18-8 shows the window this module makes when run as a top-level script. Figure 18-8. The calc0 script in action on Windows (result=160.283)Example 18-13. PP2E\Lang\Calculator\calc0.py#!/usr/local/bin/python # a simple calculator GUI: expressions run all at once with eval/exec from Tkinter import * from PP2E.Dbase.TableBrowser.guitools import frame, button, entry class CalcGui(Frame): def __init__(self, parent=None): # an extended frame Frame.__init__(self, parent) # on default top-level self.pack(expand=YES, fill=BOTH) # all parts expandable self.master.title('Python Calculator 0.1') # 6 frames plus entry self.master.iconname("pcalc1") self.names = {} # namespace for variables text = StringVar( ) entry(self, TOP, text) rows = ["abcd", "0123", "4567", "89( )"] for row in rows: frm = frame(self, TOP) for char in row: button(frm, LEFT, char, lambda x=text, y=char: x.set(x.get( ) + y)) frm = frame(self, TOP) for char in "+-*/=": button(frm, LEFT, char, lambda x=text, y=char: x.set(x.get( )+' '+y+' ')) frm = frame(self, BOTTOM) button(frm, LEFT, 'eval', lambda x=self, y=text: x.eval(y) ) button(frm, LEFT, 'clear', lambda x=text: x.set('') ) def eval(self, text): try: text.set(`eval(text.get( ), self.names, self.names)`) except SyntaxError: try: exec(text.get( ), self.names, self.names) except: text.set("ERROR") # bad as statement too? else: text.set('') # worked as a statement except: text.set("ERROR") # other eval expression errors if __name__ == '__main__': CalcGui().mainloop( ) <IP_ADDRESS> Building the GUINow, this is about as simple as a calculator can be, but it demonstrates the basics. This window comes up with buttons for entry of numbers, variable names, and operators. It is built by attaching buttons to frames: each row of buttons is a nested Frame, and the GUI itself is a Frame subclass, with an attached Entry and six embedded row frames (grids would work here, too). The calculator's frame, entry field, and buttons are made expandable in the imported guitools utility module. This calculator builds up a string to pass to the Python interpreter all at once on "eval" button presses. Because you can type any Python expression or statement in the entry field, the buttons are really just a convenience. In fact, the entry field isn't much more than a command line. Try typing import sys and then dir(sys) to display sys module attributes in the input field at the top -- it's not what you normally do with a calculator, but demonstrative nevertheless.[3]
In CalcGui's constructor, buttons are coded as lists of strings; each string represents a row and each character in the string represents a button. Lambdas with default argument values are used to set callback data for each button. The callback functions save the button's character and the linked text entry variable, so that the character can be added to the end of the entry widget's current string on a press. <IP_ADDRESS> Running code stringsThis module implements a GUI calculator in 45 lines of code (counting comments and blank lines). But to be honest, it cheats: expression evaluation is delegated to Python. In fact, the built-in eval and exec tools do most of the work here:
Both accept optional dictionaries to be used as global and local namespaces for assigning and evaluating names used in the code strings. In the calculator, self.names becomes a symbol table for running calculator expressions. A related Python function, compile, can be used to precompile code strings before passing them to eval and exec (use it if you need to run the same string many times). By default a code string's namespace defaults to the caller's namespaces. If we didn't pass in dictionaries here, the strings would run in the eval method's namespace. Since the method's local namespace goes away after the method call returns, there would be no way to retain names assigned in the string. Notice the use of nested exception handlers in the eval method:
Statements and invalid expressions might be parsed twice, but the overhead doesn't matter here, and you can't tell if a string is an expression or a statement without parsing it manually. Note that the "eval" button evaluates expressions, but = sets Python variables by running an assignment statement. Variable names are combinations of letter keys abcd (or any name typed directly). They are assigned and evaluated in a dictionary used to represent the calculator's namespace. <IP_ADDRESS> Extending and attachingClients that reuse this calculator are as simple as the calculator itself. Like most class-based Tkinter GUIs, this one can be extended in subclasses -- Example 18-14 customizes the simple calculator's constructor to add extra widgets. Example 18-14. PP2E\Lang\Calculator\calc0ext.pyfrom Tkinter import * from calc0 import CalcGui class Inner(CalcGui): # extend gui def __init__(self): CalcGui.__init__(self) Label(self, text='Calc Subclass').pack( ) # add after Button(self, text='Quit', command=self.quit).pack( ) # top implied Inner().mainloop( ) It can also be embedded in a container class -- Example 18-15 attaches the simple calculator's widget package, and extras, to a common parent. Example 18-15. PP2E\Lang\Calculator\calc0emb.pyfrom Tkinter import * from calc0 import CalcGui # add parent, no master calls class Outer: def __init__(self, parent): # embed gui Label(parent, text='Calc Attachment').pack( ) # side=top CalcGui(parent) # add calc frame Button(parent, text='Quit', command=parent.quit).pack( ) root = Tk( ) Outer(root) root.mainloop( ) Figure 18-9 shows the result of running both of these scripts from different command lines. Both have a distinct input field at the top. This works; but to see a more practical application of such reuse techniques, we need to make the underlying calculator more practical, too. Figure 18-9. The calc0 script's object attached and extended18.7.2 Pycalc -- A Real Calculator GUIOf course, real calculators don't usually work by building up expression strings and evaluating them all at once; that approach is really little more than a glorified Python command line. Traditionally, expressions are evaluated in piecemeal fashion as they are entered, and temporary results are displayed as soon as they are computed. Implementing this behavior is a bit more work: expressions must be evaluated manually instead of calling the eval function only once. But the end result is much more useful and intuitive.
This section presents the implementation of PyCalc -- a Python/Tkinter program that implements such a traditional calculator GUI. Although its evaluation logic is more complex than the simpler calculator above, it demonstrates advanced programming techniques and serves as an interesting finale for this chapter. <IP_ADDRESS> Running PyCalcAs usual, let's look at the GUI before the code. You can run PyCalc from the PyGadgets and PyDemos launcher bars at the top of the examples tree, or by directly running file calculator.py listed below (e.g., click it in a file explorer). Figure 18-10 shows PyCalc's main window. By default, it shows operand buttons in black-on-blue (and opposite for operator buttons), but font and color options can be passed in to the GUI class's constructor method. Of course, that means gray-on-gray in this book, so you'll have to run PyCalc yourself to see what I mean. Figure 18-10. PyCalc calculator at work on WindowsIf you do run this, you'll notice that PyCalc implements a normal calculator model -- expressions are evaluated as entered, not all at once at the end. That is, parts of an expression are computed and displayed as soon as operator precedence and manually typed parentheses allow. I'll explain how this evaluation works in a moment. PyCalc's CalcGui class builds the GUI interface as frames of buttons much like the simple calculator of the previous section, but PyCalc adds a host of new features. Among them are another row of action buttons, inherited methods from GuiMixin (presented in Chapter 9), a new "cmd" button that pops up nonmodal dialogs for entry of arbitrary Python code, and a recent calculations history pop-up. Figure 18-11 captures some of PyCalc's pop-up windows. Figure 18-11. PyCalc calculator with some of its pop-upsYou may enter expressions in PyCalc by clicking buttons in the GUI, typing full expressions in command-line pop-ups, or typing keys on your keyboard. PyCalc intercepts key press events and interprets them the same as corresponding button presses; typing + is like pressing button +, the space bar key is "clear", Enter is "eval", backspace erases a character, and ? is like pressing "help". The command-line pop-up windows are nonmodal (you can pop up as many as you like). They accept any Python code -- press the Run button or your Enter key to evaluate text in the input field. The result of evaluating this code in the calculator's namespace dictionary is thrown up in the main window, for use in larger expressions. You can use this as an escape mechanism to employ external tools in your calculations. For instance, you can import and use functions coded in Python or C within these pop-ups. The current value in the main calculator window is stored in newly opened command-line pop-ups, too, for use in typed expressions. PyCalc supports long integers (unlimited precision), negatives, and floating-point numbers, just because Python does: individual operands and expressions are still evaluated with the eval built-in, which calls the Python parser/interpreter at run-time. Variable names can be assigned and referenced in the main window with the letter, =, and "eval" keys; they are assigned in the calculator's namespace dictionary (more complex variable names may be typed in command-line pop-ups). Note the use of pi in the history window: PyCalc preimports names in the math and random modules into the namespace where expressions are evaluated. <IP_ADDRESS> Evaluating expressions with stacksNow that you have the general idea of what PyCalc does, I need to say a little bit about how it does what it does. Most of the changes in this version involve managing the expression display and evaluating expressions. PyCalc is structured as two classes:
As you can see from this, the magic of expression evaluation boils down to juggling the operator and operand stacks. While scanning expression strings from left to right as they are entered, operands are pushed along the way, but operators delimit operands and may trigger temporary results before they are pushed. Here's the general scenario:
In the end, the last value on the operands stack is displayed in the calculator's entry field, ready for use in another operation. This evaluation algorithm is probably best described by working through examples. Let's step through the entry of a few expressions and watch the evaluation stacks grow. PyCalc stack tracing is enabled with the debugme flag in the module; if true, the operator and operand stacks are displayed on stdout each time the Evaluator class is about to apply an operator and reduce (pop) the stacks. A tuple holding the stack lists (operators, operands) is printed on each stack reduction; tops of stack are at the ends of the lists. For instance, here is the console output after typing and evaluating a simple string: 1) Entered keys: "5 * 3 + 4 <eval>" [result = 19] (['*'], ['5', '3']) [on '+' press: displays "15"] (['+'], ['15', '4']) [on 'eval' press: displays "19"] Note that the pending (stacked) * subexpression is evaluated when the + is pressed: * operators bind tighter than +, so the code is evaluated immediately before the + operator is pushed. When the + button is pressed, the entry field contains 3. In general, the entry field always holds the prior operand when an operator button is pressed. Since the text entry's value is pushed onto the operands stack before the operator is applied, we have to pop results before displaying them after "eval" or ) is pressed (otherwise the results are pushed onto the stack twice): 2) "5 + 3 * 4 <eval>" [result = 17] (['+', '*'], ['5', '3', '4']) [on 'eval' press] (['+'], ['5', '12']) [displays "17"] Here, the pending + isn't evaluated when the * button is pressed: since * binds tighter, we need to postpone the + until the * can be evaluated. The * operator isn't popped until its right operand has been seen. On the "eval" press there are two operators to pop and apply to operand stack entries: 3) "5 + 3 + 4 <eval>" [result = 12] (['+'], ['5', '3']) [on the second '+'] (['+'], ['8', '4']) [on 'eval'] For strings of same-precedence operators like this one, we pop and evaluate immediately as we scan left to right, instead of postponing evaluation. This results in a left-associative evaluation, in the absence of parentheses: 5+3+4 is evaluated as ((5+3)+4). Order doesn't matter for + and * operations: 4) "1 + 3 * ( 1 + 3 * 4 ) <eval>" [result = 40] (['+', '*', '(', '+', '*'], ['1', '3', '1', '3', '4']) [on ')'] (['+', '*', '(', '+'], ['1', '3', '1', '12']) [displays "13"] (['+', '*'], ['1', '3', '13']) [on 'eval'] (['+'], ['1', '39']) In this case, all the operators and operands are stacked (postponed) until we press the ) button at the end. When the ) button is pressed, the parenthesized subexpression is popped and evaluated, and 13 is displayed in the entry field. On pressing "eval", the rest is evaluated, and the final result (40) is shown. The result is the left operand of another operator. In fact, any temporary result can be used again: if we keep pressing an operator button without typing new operands, it's reapplied to the result of the prior press. Figure 18-12 shows how the two stacks look at their highest level while scanning the expression in the preceding example trace. The top operator is applied to the top two operands and the result is pushed back for the operator below: 5) "1 + 3 * ( 1 + 3 * 4 <eval>" [result = *ERROR*] (['+', '*', '(', '+', '*'], ['1', '3', '1', '3', '4']) [on eval] (['+', '*', '(', '+'], ['1', '3', '1', '12']) (['+', '*', '('], ['1', '3', '13']) (['+', '*'], ['1', '*ERROR*']) (['+'], ['*ERROR*']) (['+'], ['*ERROR*', '*ERROR*']) Figure 18-12. Evaluation stacks: 1 + 3 * (1 + 3 * 4)This string triggers an error. PyCalc is casual about error handling. Many errors are made impossible by the algorithm itself, but things like unmatched parentheses still trip up the evaluator. But instead of trying to detect all possible error cases explicitly, a general try statement in the reduce method is used to catch them all: expression errors, undefined name errors, syntax errors, etc. Operands and temporary results are always stacked as strings, and each operator are applied by calling eval. When an error occurs inside an expression, a result operand of *ERROR* is pushed, which makes all remaining operators fail in eval, too. *ERROR* percolates to the top of the expression. At the end, it's the last operand and is displayed in the text entry field to alert you of the mistake. <IP_ADDRESS> PyCalc source codeExample 18-16 contains the PyCalc source module that puts these ideas to work in the context of a GUI. It's a single-file implementation (not counting utilities imported and reused). Study the source for more details; and as usual, there's no substitute for interacting with the program on your own to get a better feel for its functionality. Example 18-16. PP2E\Lang\Calculator\calculator.py#!/usr/local/bin/python ######################################################################### # PyCalc 2.0: a Python/Tkinter calculator program and GUI component. # evaluates expressions as they are entered, catches keyboard keys # for expression entry; adds integrated command-line popups, recent # calculations history display popup, fonts and colors configuration, # help and about popups, preimported math/random constants, and more; ######################################################################### from Tkinter import * # widgets, consts from PP2E.Gui.Tools.guimixin import GuiMixin # quit method from PP2E.Dbase.TableBrowser.guitools import * # widget builders Fg, Bg, Font = 'black', 'skyblue', ('courier', 16, 'bold') # default config debugme = 1 def trace(*args): if debugme: print args ########################################### # the main class - handles user interface; # an extended Frame, on new Toplevel, or # embedded in another container widget ########################################### class CalcGui(GuiMixin, Frame): Operators = "+-*/=" # button lists Operands = ["abcd", "0123", "4567", "89( )"] # customizable def __init__(self, parent=None, fg=Fg, bg=Bg, font=Font): Frame.__init__(self, parent) self.pack(expand=YES, fill=BOTH) # all parts expandable self.eval = Evaluator( ) # embed a stack handler self.text = StringVar( ) # make a linked variable self.text.set("0") self.erase = 1 # clear "0" text next self.makeWidgets(fg, bg, font) # build the gui itself if not parent or not isinstance(parent, Frame): self.master.title('PyCalc 2.0') # title iff owns window self.master.iconname("PyCalc") # ditto for key bindings self.master.bind('<KeyPress>', self.onKeyboard) self.entry.config(state='disabled') else: self.entry.config(state='normal') self.entry.focus( ) def makeWidgets(self, fg, bg, font): # 7 frames plus text-entry self.entry = entry(self, TOP, self.text) # font, color configurable for row in self.Operands: frm = frame(self, TOP) for char in row: button(frm, LEFT, char, lambda x=self, y=char: x.onOperand(y), fg=fg, bg=bg, font=font) frm = frame(self, TOP) for char in self.Operators: button(frm, LEFT, char, lambda x=self, y=char: x.onOperator(y), fg=bg, bg=fg, font=font) frm = frame(self, TOP) button(frm, LEFT, 'cmd ', self.onMakeCmdline) button(frm, LEFT, 'dot ', lambda x=self: x.onOperand('.')) button(frm, LEFT, 'long', lambda x=self: x.text.set(x.text.get( )+'L')) button(frm, LEFT, 'help', self.help) button(frm, LEFT, 'quit', self.quit) # from guimixin frm = frame(self, BOTTOM) button(frm, LEFT, 'eval ', self.onEval) button(frm, LEFT, 'hist ', self.onHist) button(frm, LEFT, 'clear', self.onClear) def onClear(self): self.eval.clear( ) self.text.set('0') self.erase = 1 def onEval(self): self.eval.shiftOpnd(self.text.get( )) # last or only opnd self.eval.closeall( ) # apply all optrs left self.text.set(self.eval.popOpnd( )) # need to pop: optr next? self.erase = 1 def onOperand(self, char): if char == '(': self.eval.open( ) self.text.set('(') # clear text next self.erase = 1 elif char == ')': self.eval.shiftOpnd(self.text.get( )) # last or only nested opnd self.eval.close( ) # pop here too: optr next? self.text.set(self.eval.popOpnd( )) self.erase = 1 else: if self.erase: self.text.set(char) # clears last value else: self.text.set(self.text.get( ) + char) # else append to opnd self.erase = 0 def onOperator(self, char): self.eval.shiftOpnd(self.text.get( )) # push opnd on left self.eval.shiftOptr(char) # eval exprs to left? self.text.set(self.eval.topOpnd( )) # push optr, show opnd|result self.erase = 1 # erased on next opnd|'(' def onMakeCmdline(self): new = Toplevel( ) # new top-level window new.title('PyCalc command line') # arbitrary python code frm = frame(new, TOP) # only the Entry expands label(frm, LEFT, '>>>').pack(expand=NO) var = StringVar( ) ent = entry(frm, LEFT, var, width=40) onButton = (lambda s=self, v=var, e=ent: s.onCmdline(v,e)) onReturn = (lambda event, s=self, v=var, e=ent: s.onCmdline(v,e)) button(frm, RIGHT, 'Run', onButton).pack(expand=NO) ent.bind('<Return>', onReturn) var.set(self.text.get( )) def onCmdline(self, var, ent): # eval cmdline popup input try: value = self.eval.runstring(var.get( )) var.set('OKAY') if value != None: # run in eval namespace dict self.text.set(value) # expression or statement self.erase = 1 var.set('OKAY => '+ value) except: # result in calc field var.set('ERROR') # status in popup field ent.icursor(END) # insert point after text ent.select_range(0, END) # select msg so next key deletes def onKeyboard(self, event): pressed = event.char # on keyboard press event if pressed != '': # pretend button was pressed if pressed in self.Operators: self.onOperator(pressed) else: for row in self.Operands: if pressed in row: self.onOperand(pressed) break else: if pressed == '.': self.onOperand(pressed) # can start opnd if pressed in 'Ll': self.text.set(self.text.get( )+'L') # can't: no erase elif pressed == '\r': self.onEval( ) # enter key = eval elif pressed == ' ': self.onClear( ) # spacebar = clear elif pressed == '\b': self.text.set(self.text.get( )[:-1]) # backspace elif pressed == '?': self.help( ) def onHist(self): # show recent calcs log popup # self.infobox('PyCalc History', self.eval.getHist( )) from ScrolledText import ScrolledText new = Toplevel( ) # make new window ok = Button(new, text="OK", command=new.destroy) ok.pack(pady=1, side=BOTTOM) # pack first=clip last text = ScrolledText(new, bg='beige') # add Text + scrollbar text.insert('0.0', self.eval.getHist( )) # get Evaluator text text.pack(expand=YES, fill=BOTH) # new window goes away on ok press or enter key new.title("PyCalc History") new.bind("<Return>", (lambda event, new=new: new.destroy( ))) ok.focus_set( ) # make new window modal: new.grab_set( ) # get keyboard focus, grab app new.wait_window( ) # don't return till new.destroy def help(self): self.infobox('PyCalc', 'PyCalc 2.0\n' 'A Python/Tk calculator\n' 'August, 1999\n' 'Programming Python 2E\n\n' 'Use mouse or keyboard to\n' 'input numbers and operators,\n' 'or type code in cmd popup') #################################### # the expression evaluator class # embedded in and used by a CalcGui # instance, to perform calculations #################################### class Evaluator: def __init__(self): self.names = {} # a names-space for my vars self.opnd, self.optr = [], [] # two empty stacks self.hist = [] # my prev calcs history log self.runstring("from math import *") # preimport math modules self.runstring("from random import *") # into calc's namespace def clear(self): self.opnd, self.optr = [], [] # leave names intact if len(self.hist) > 64: # don't let hist get too big self.hist = ['clear'] else: self.hist.append('--clear--') def popOpnd(self): value = self.opnd[-1] # pop/return top|last opnd self.opnd[-1:] = [] # to display and shift next return value def topOpnd(self): return self.opnd[-1] # top operand (end of list) def open(self): self.optr.append('(') # treat '(' like an operator def close(self): # on ')' pop downto higest '(' self.shiftOptr(')') # ok if empty: stays empty self.optr[-2:] = [] # pop, or added again by optr def closeall(self): while self.optr: # force rest on 'eval' self.reduce( ) # last may be a var name try: self.opnd[0] = self.runstring(self.opnd[0]) except: self.opnd[0] = '*ERROR*' # pop else added again next: afterMe = {'*': ['+', '-', '(', '='], # class member '/': ['+', '-', '(', '='], # optrs to not pop for key '+': ['(', '='], # if prior optr is this: push '-': ['(', '='], # else: pop/eval prior optr ')': ['(', '='], # all left-associative as is '=': ['('] } def shiftOpnd(self, newopnd): # push opnd at optr, ')', eval self.opnd.append(newopnd) def shiftOptr(self, newoptr): # apply ops with <= priority while (self.optr and self.optr[-1] not in self.afterMe[newoptr]): self.reduce( ) self.optr.append(newoptr) # push this op above result # optrs assume next opnd erases def reduce(self): trace(self.optr, self.opnd) try: # collapse the top expr operator = self.optr[-1] # pop top optr (at end) [left, right] = self.opnd[-2:] # pop top 2 opnds (at end) self.optr[-1:] = [] # delete slice in-place self.opnd[-2:] = [] result = self.runstring(left + operator + right) if result == None: result = left # assignment? key var name self.opnd.append(result) # push result string back except: self.opnd.append('*ERROR*') # stack/number/name error def runstring(self, code): try: result = `eval(code, self.names, self.names)` # try expr: string self.hist.append(code + ' => ' + result) # add to hist log except: exec code in self.names, self.names # try stmt: None self.hist.append(code) result = None return result def getHist(self): import string return string.join(self.hist, '\n') def getCalcArgs( ): from sys import argv config = {} # get cmdline args in a dict for arg in argv[1:]: # ex: -bg black -fg red if arg in ['-bg', '-fg']: # font not yet supported try: config[arg[1:]] = argv[argv.index(arg) + 1] except: pass return config if __name__ == '__main__': apply(CalcGui, (), getCalcArgs()).mainloop( ) # on default toplevel window <IP_ADDRESS> Using PyCalc as a componentPyCalc serves a standalone program on my desktop, but it's also useful in the context of other GUIs. Like most of the GUI classes in this book, PyCalc can be customized with subclass extensions, or embedded in a larger GUI with attachment. The module in Example 18-17 demonstrates one way to reuse PyCalc's CalcGui class by extending and embedding, much as done for the simple calculator earlier. Example 18-17. PP2E\Lang\Calculator\calculator_test.py########################################################################## # test calculator use as an extended and embedded gui component; ########################################################################## from Tkinter import * from calculator import CalcGui from PP2E.Dbase.TableBrowser.guitools import * def calcContainer(parent=None): frm = Frame(parent) frm.pack(expand=YES, fill=BOTH) Label(frm, text='Calc Container').pack(side=TOP) CalcGui(frm) Label(frm, text='Calc Container').pack(side=BOTTOM) return frm class calcSubclass(CalcGui): def makeWidgets(self, fg, bg, font): Label(self, text='Calc Subclass').pack(side=TOP) Label(self, text='Calc Subclass').pack(side=BOTTOM) CalcGui.makeWidgets(self, fg, bg, font) #Label(self, text='Calc Subclass').pack(side=BOTTOM) if __name__ == '__main__': import sys if len(sys.argv) == 1: # % calculator_test.py root = Tk( ) # run 3 calcs in same process CalcGui(Toplevel( )) # each in a new toplevel window calcContainer(Toplevel( )) calcSubclass(Toplevel( )) Button(root, text='quit', command=root.quit).pack( ) root.mainloop( ) if len(sys.argv) == 2: # % calculator_testl.py - CalcGui().mainloop( ) # as a standalone window (default root) elif len(sys.argv) == 3: # % calculator_test.py - - calcContainer().mainloop( ) # as an embedded component elif len(sys.argv) == 4: # % calculator_test.py - - - calcSubclass().mainloop( ) # as a customized superclass Figure 18-13 shows the result of running this script with no command-line arguments. We get instances of the original calculator class, plus the container and subclass classes defined in this script, all attached to new top-level windows. Figure 18-13. The calculator_test script: attaching and extendingThese two windows on the right reuse the core PyCalc code running in the window on the left. All these windows all run in the same process (e.g., quitting one quits them all), but they all function as independent windows. Note that when running three calculators in the same process like this, each has its own distinct expression evaluation namespace because it's a class instance attribute, not a global module-level variable. Because of that, variables set in one calculator are set in that calculator only, and don't overwrite settings made in other windows. Similarly, each calculator has its own evaluation stack manager object, such that calculations in one window don't appear in or impact other windows at all. The two extensions in this script are artificial, of course -- they simply add labels at the top and bottom of the window -- but the concept is widely applicable. You could reuse the calculator's class by attaching it to any GUI that needs a calculator, and customize it with subclasses arbitrarily. It's a reusable widget. <IP_ADDRESS> Adding new buttons in new componentsOne obvious way to reuse the calculator is to add additional expression feature buttons -- square roots, inverses, cubes, and the like. You can type such operations in the command-line pop-ups, but buttons are a bit more convenient. Such features could also be added to the main calculator implementation itself; but since the set of features that will be useful may vary per user and application, a better approach may be to add them in separate extensions. For instance, the class in Example 18-18 adds a few extra buttons to PyCalc by embedding (i.e., attaching) it in a container. Example 18-18. PP2E\Lang\Calculator\calculator_plus_emb.py######################################################################## # a container with an extra row of buttons for common operations; # a more useful customization: adds buttons for more operations (sqrt, # 1/x, etc.) by embedding/composition, not subclassing; new buttons are # added after entire CalGui frame because of the packing order/options; ######################################################################## from Tkinter import * from calculator import CalcGui, getCalcArgs from PP2E.Dbase.TableBrowser.guitools import frame, button, label class CalcGuiPlus(Toplevel): def __init__(self, **args): Toplevel.__init__(self) label(self, TOP, 'PyCalc Plus - Container') self.calc = apply(CalcGui, (self,), args) frm = frame(self, BOTTOM) extras = [('sqrt', 'sqrt(%s)'), ('x^2 ', '(%s)**2'), ('x^3 ', '(%s)**3'), ('1/x ', '1.0/(%s)')] for (lab, expr) in extras: button(frm, LEFT, lab, (lambda m=self.onExtra, e=expr: m(e)) ) button(frm, LEFT, ' pi ', self.onPi) def onExtra(self, expr): text = self.calc.text eval = self.calc.eval try: text.set(eval.runstring(expr % text.get( ))) except: text.set('ERROR') def onPi(self): self.calc.text.set(self.calc.eval.runstring('pi')) if __name__ == '__main__': root = Tk( ) button(root, TOP, 'Quit', root.quit) apply(CalcGuiPlus, (), getCalcArgs()).mainloop( ) # -bg,-fg to calcgui Because PyCalc is coded as a Python class, you can always achieve a similar effect by extending PyCalc in a new subclass instead of embedding it, as shown in Example 18-19. Example 18-19. PP2E\Lang\Calculator\calculator_plus_ext.py############################################################################## # a customization with an extra row of buttons for common operations; # a more useful customization: adds buttons for more operations (sqrt, # 1/x, etc.) by subclassing to extend the original class, not embedding; # new buttons show up before frame attached to bottom be calcgui class; ############################################################################## from Tkinter import * from calculator import CalcGui, getCalcArgs from PP2E.Dbase.TableBrowser.guitools import * class CalcGuiPlus(CalcGui): def makeWidgets(self, *args): label(self, TOP, 'PyCalc Plus - Subclass') apply(CalcGui.makeWidgets, (self,) + args) frm = frame(self, BOTTOM) extras = [('sqrt', 'sqrt(%s)'), ('x^2 ', '(%s)**2'), ('x^3 ', '(%s)**3'), ('1/x ', '1.0/(%s)')] for (lab, expr) in extras: button(frm, LEFT, lab, (lambda m=self.onExtra, e=expr: m(e)) ) button(frm, LEFT, ' pi ', self.onPi) def onExtra(self, expr): try: self.text.set(self.eval.runstring(expr % self.text.get( ))) except: self.text.set('ERROR') def onPi(self): self.text.set(self.eval.runstring('pi')) if __name__ == '__main__': apply(CalcGuiPlus, (), getCalcArgs()).mainloop( ) # passes -bg, -fg on Notice that these buttons' callbacks use 1.0/x to force float-point division to be used for inverses (integer division truncates remainders), and wrap entry field values in parentheses (to sidestep precedence issues). They could instead convert the entry's text to a number and do real math, but Python does all the work automatically when expression strings are run raw. Also note that the buttons added by these scripts simply operate on the current value in the entry field, immediately. That's not quite the same as expression operators applied with the stacks evaluator (additional customizations are needed to make them true operators). Still, these buttons prove the point these scripts are out to make -- they use PyCalc as a component, both from the outside and below. Finally, to test both of the extended calculator classes, as well as PyCalc configuration options, the script in Example 18-20 puts up four distinct calculator windows (this is the script run by PyDemos). Example 18-20. PP2E\Lang\Calculator\calculator_plusplus.py#!/usr/local/bin/python from Tkinter import Tk, Button, Toplevel import calculator, calculator_plus_ext, calculator_plus_emb # demo all 3 calculator flavors at once # each is a distinct calculator object and window root=Tk( ) calculator.CalcGui(Toplevel( )) calculator.CalcGui(Toplevel( ), fg='white', bg='purple') calculator_plus_ext.CalcGuiPlus(Toplevel( ), fg='gold', bg='black') calculator_plus_emb.CalcGuiPlus(fg='black', bg='red') Button(root, text='Quit Calcs', command=root.quit).pack( ) root.mainloop( ) Figure 18-14 shows the result -- four independent calculators in top-level windows within the same process. The windows on the left and right represent specialized reuses of PyCalc as a component. Although it may not be obvious in this book, all four use different color schemes; calculator classes accept color and font configuration options and pass them down the call chain as needed. Figure 18-14. The calculator_plusplus script: extend, embed, and configureAs we learned earlier, these calculators could also be run as independent processes by spawning command lines with the launchmodes module we met in Chapter 3. In fact, that's how the PyGadgets and PyDemos launcher bars run calculators, so see their code for more details.
|
| I l@ve RuBoard |


This page performs automated unit tests on each of the JSLINQ Samples.Just click "Run Test" to start the Unit Tests. The results will be displayed below once they are finished.


{% extends 'base.html' %} {% load i18n %} {% block body_class %}account{% endblock %} {% block page_title %}{% trans "Bad Token" %}{% endblock %} {% block site_main %} {% trans "Bad Token" %} {% url "account_password_reset" as url %} {% blocktrans %}The password reset link was invalid, possibly because it has already been used.{% endblocktrans %} {% blocktrans %}Please request a new password reset.{% endblocktrans %} {% endblock %}
{% blocktrans %}The password reset link was invalid, possibly because it has already been used.{% endblocktrans %}
{% blocktrans %}Please request a new password reset.{% endblocktrans %}


1992 - Meets Detroit native musician Amp Fiddler, who is very impressed by what Dilla is able to accomplish with such limited tools
1995 - Forms the group 1st Down with fellow Detroit rapper Phat Kat and become the first Detroit hip-hop duo to sign with a major record label ( PayDay Records ). Later that year the label would go under
Also in 1995 - He records the "Yester Years EP" with the Elementz ( a group consisting of Proof, Thyme, and Mudd )
1996 - He forms the group Slum Village along with T3 and Baatin.They record the groups debut album Fan-Tas-Tic ( Vol.1 )
1997 - Fan-Tas-Tic ( Vol.1 ) is released.it quicky belcomes popular with fans of Detroit hip-hop and also gains the attention of Q-Tip, who hailed the group as successors to A Tribe Called Quest. However, J Dilla felt uncomfortable with
the comparison and voiced it in serveral interviews
By the mid-90's - JAY DEE was known as a major hip-hop prospect, with a string of singles and remix projects for acts such as Janet Jackson, De La Soul, Pharcyde, Busta Rhymes, A Tribe Called Quest and Q-Tip's solo project amongst others.
The majority of these productions were released without his name recognition, being credited to The Ummah, a production collective composed of Q-Tip and Ali Shaheed Muhammd of A Tribe Called Quest and later Raphael Saadiq of Tony! Toni! Tone!
2000 - Marked the major label debut of Slum Village with Fantastic,Vol.2 creating a new folowing for Jay Dee as a producer and a MC. He was also a founding member of the production collective known as The Soulquarians( along with ?uestlove,D'Angelo,and
James Poyser amongst others ) which earned him more recognition and buzz
2001 - He debuts as a solo artist with the single "Fuck the Police ( Up Above Records ) followed by the album "Welcome 2 Detroit" which kicked off the British independent record label BBE's "Beat Generaton" series
also in 2001 - Jay Dee began using the name "J Dilla"( an attempt to differentiate himself from Jermaine Dupri also goes by J.D. ) and left Slum Village to prusue a major label solo career with MCA Records
2002 - Dilla produces Frank-N-Dank's 48 Hours as well as a solo album, but neither record would ever be released, although the former did eventually surface through bootlegging
2003 - J Dilla and L.A. based producer Madlib combine to form the group JayLib and release the album Champion Sound
2004 - J Dilla relocates from Detroit to Los Angeles.Dramatic weight loss due to medication and illness forcing him to publicly confirm speculation about his health
2005 - Publications such as XXL( June 2005 ) confirmed rumors of ill health and hospitalization during this period, but these were downplayed by Jay himself. The seriousness of his condition became public in November of 2005 when J Dilla
toured Europe in a wheelchair. It was later revealed that he suffered from thrombotic thrombocytopenic purpura ( a rare blood disease ) and possibly lupus
2006 - James Dewitt Yancey better known as J Dilla passes away on February 10th just three days after his 32nd birthday and the release of his final album Donuts, at his home in Los Angeles,Ca. According to his mother, Maureen
Yancey, the cause of death was cardiac arrest
"J Dilla was a master."
For more information on the life and work of J Dilla, head over to his Wikipedia Page.


**** COMMODORE 64 BASIC V2 ****
64K RAM SYSTEM 38911 BASIC BYTES FREE
SPECIAL ZENDESK EDITION
READY.
ENTER ZENDESK TICKET NUMBER.
THEN PRESS PLAY ON TAPE.
AGENTS LOADED!


nips nips2008 nips2008-85 nips2008-85-reference knowledge-graph by maker-knowledge-mining
Source: pdf
Author: Karthik Sridharan, Shai Shalev-shwartz, Nathan Srebro
Abstract: We study convergence properties of empirical minimization of a stochastic strongly convex objective, where the stochastic component is linear. We show that the value attained by the empirical minimizer converges to the optimal value with rate 1/n. The result applies, in particular, to the SVM objective. Thus, we obtain a rate of 1/n on the convergence of the SVM objective (with ﬁxed regularization parameter) to its inﬁnite data limit. We demonstrate how this is essential for obtaining certain type of oracle inequalities for SVMs. The results extend also to approximate minimization as well as to strong convexity with respect to an arbitrary norm, and so also to objectives regularized using other p norms. 1
[1] E. Hazan, A. Kalai, S. Kale, and A. Agarwal. Logarithmic regret algorithms for online convex optimization. In Proceedings of the Nineteenth Annual Conference on Computational Learning Theory, 2006.
[2] S. Shalev-Shwartz. Online Learning: Theory, Algorithms, and Applications. PhD thesis, The Hebrew University, 2007.
[3] T. Zhang. Covering number bounds of certain regularized linear function classes. J. Mach. Learn. Res., 2:527–550, 2002.
[4] I. Steinwart, D. Hush, and C. Scovel. A new concentration result for regularized risk minimizers. Highdimensional Probability IV, in IMS Lecture Notes, 51:260–275, 2006.
[5] P. L. Bartlett, O. Bousquet, and S. Mendelson. Localized rademacher complexities. In COLT ’02: Proceedings of the 15th Annual Conference on Computational Learning Theory, pages 44–58, London, UK, 2002. Springer-Verlag.
[6] O. Bousquet, S. Boucheron, and G. Lugosi. Introduction to statistical learning theory. In O. Bousquet, U.v. Luxburg, and G. R¨ tsch, editors, Advanced Lectures in Machine Learning, pages 169–207. Springer, a 2004.
[7] S. M. Kakade, K. Sridharan, and A. Tewari. On the complexity of linear prediction: Risk bounds, margin bounds, and regularization. In NIPS, 2008.
[8] W. S. Lee, P. L. Bartlett, and R. C. Williamson. The importance of convexity in learning with squared loss. In Computational Learing Theory, pages 140–146, 1996.
[9] O. Bousquet. Concentration Inequalities and Empirical Processes Theory Applied to the Analysis of Learning Algorithms. PhD thesis, Ecole Polytechnique, 2002.
[10] A. Tsybakov. Optimal aggregation of classiﬁers in statistical learning. Annals of Statistics, 32:135–166, 2004.
[11] I. Steinwart and C. Scovel. Fast rates for support vector machines using gaussian kernels. ANNALS OF STATISTICS, 35:575, 2007.
[12] P. L. Bartlett, M. I. Jordan, and J. D. McAuliffe. Convexity, classiﬁcation, and risk bounds. Journal of the American Statistical Association, 101:138–156, March 2006. 8


The only online store you will ever need for all your windsurfing and kitesurfing and SUP needs
Super easy going freeride boards based on the X-Cite Ride shape concept with additional control and super easy jibing.
Now is open!


Progress bar - Example
42%
42%
23%
23%
23%
23%
88%
88%
58%
58%
65%
65%
65%
35%
65%
35%
Loading...
Loading...
Cancel...
Cancel...
Small
Small
Large
Large
Rounded
Rounded


Do you have the Right Stuff?
Courage
You will need to be brave on Mars...
Select all fears and phobias that apply
None
Snakes
Spiders from Mars
Indoor Restaurants
Confined Spaces
Isolation
Dying Far from Home
Other


RT @blowmage: We are going to send MWRC off in style. Gonna be amazing. So much in store.  Gonna be amazing. So much in store. You srsly don't want to miss it.
https://t.co/JXz…
1/6/2016, 8:33:04 AM
Favs: 0
Retweets: 0
link


Prasoon Mishra
Projects
Resume
Prasoon Mishra
I am
a avid reader. | a lazy programmer. | aggresive chess player. | a keen observer.
My interests are
big data analytics. | data visualization. | internet of things. | cloud computing. | distributed systems.
I have worked with
Python. | Django. | Java. | HTML/CSS. | Javascript. | jQuery. | MySQL. | SPARQL. | C/C++. | Verilog. | Latex.
Get in touch


Lake Victoria (Nam Lolwe in Luo; 'Nnalubaale in Luganda; Nyanza in some Bantu languages)[6] is one of the African Great Lakes. The lake was renamed Lake Victoria after Queen Victoria by the explorer John Hanning Speke, in his reports—the first Briton to document it. (It has since been recognized that the native guides used the name Lake Nyanza to describe it to him.) Speke accomplished this in 1858, while on an expedition with Richard Francis Burton to locate the source of the Nile River.[7][8] This expedition was financially sponsored by the Royal Geographic Society.
Lake Victoria (Nam Lolwe in Luo; 'Nnalubaale in Luganda; Nyanza in some Bantu languages)[6] is one of the African Great Lakes. The lake was renamed Lake Victoria after Queen Victoria by the explorer John Hanning Speke, in his reports—the first Briton to document it. (It has since been recognized that the native guides used the name Lake Nyanza to describe it to him.) Speke accomplished this in 1858, while on an expedition with Richard Francis Burton to locate the source of the Nile River.[7][8] This expedition was financially sponsored by the Royal Geographic Society.


KeeWeb Plugin Creation Tool
Plugin type:
JS code
JS code + CSS styles
CSS styles (not themes)
Locale
CSS Theme
Plugin name (lowercase letters and dashes):
Description (human-readable):
Author name:
Author email:
Author URL:
Plugin page URL:
License:
Locale code (xx or xx-XX):
Locale name (human-readable):
Theme class (lowercase letters and dashes):
Theme name (human-readable):
Theme colors:
Normal text and
error
Button
Hollow button
Here's a menu
I'm selected
Download your plugin
You're awesome!
Now it's time to create your plugin. Here are some
docs
for you to start.
Your plugin manifest


Step 1.
Go toDashboard » Appearance » Customize
.
Theme includes a backend color picker in the theme options that allows you to easily change the color of any element throughout the entire theme. You can also choose 7 of our color schemes. It has Unlimited Color Options, keep the "Predefined Color Scheme" simultaneously.
Dashboard » Appearance » Customize
.


This is the declaration for the Study::Guts class, the abstract object to which a Study handle points.
This is in a separate header file from Study because only people who are extending the Study class to make their own Studies need to be aware of the details. End users access only methods from the Study class and classes derived from Study, never anything from Study::Guts or its derived classes.
Below is the physical layout of memory for a Study, and which portions are allocated by the client program and which by the binary library code. For binary compatiblity, only the side which allocated a piece of memory can access it. Exception: both the client and library side must agree on the virtual function table (VFT) ordering of the client's virtual functions.
* CLIENT SIDE . LIBRARY SIDE
* .
* Study Study::Guts . Study::Guts::GutsRep
* --------------- ------------------ . -------------
* | Study::Guts* | --> | Study::GutsRep* | --> | GutsRep |
* --------------- ------------------ . | |
* ^ | Concrete Guts | . | Other opaque|
* | | class data and | . | stuff |
* =============== | client-side VFT | . | |
* Concrete Study ------------------ . | |
* adds no data . -------------
* members
*
If the concrete Study::Guts class also has an opaque implementation, as it will for concrete Studies provided by the SimTK Core, then the Study author should expose only the data-free handle class derived from Study.


Survey Category
All surveys are organized in survey category. Each category contains surveys and sub-categories. The top level category is root category. This root category is created by ATS with initial installation. It is editable but can not be deleted.
A list of surveys will show in the current category. To jump to another category, select from category drop-down box.
Functional buttons
-
create a new category under current category
- Category Name: Name of category
- sort order: sort survey and sub-category by alphabetic, created date, or created date reversed
- Description: Description of category
After new sub-category is created, current category will be changed to this new category.
-
Make changes on the category name, sort order and description
-
delete current category. Category can not be deleted if there are any surveys or sub-categories. You must delete the surveys and sub-categories first.
-
create a new survey in current category
- survey name: name of the survey
- survey heading (title): which will display in the survey.
- survey theme: select the theme of the survey, there are blue, green, yellow, pink, grey and white
Links
The links direct you to edit the selected survey. For detail, see survey section.
From the list of surveys in the current category, you can click the link on
-
go to survey dashboard of current survey.
-
go to question list of current survey
-
go to survey invitation of current survey
-
preview current survey
-
delete current survey
Navigation bar
Show you current category and link to all its parent categories
Jump to another category:
There is a select drop-down box, which list all the categories within ATS. To jump to another category, simple select the category from the list.
The category name ending with ** is the current category.


Jslet - Formula Field Demo
Configurate formula field and see how it works.
Sales Transaction List
Edit Panel
Change value of "price" field or "num" field, and see the value of field "amount":
Demo Content:
Field formula: amount = num * price.
Field "amount" is readonly.


Wendy:
"At...lan...ta..."
No, I don't remember anything about that.
Old Pavel... research wing... no, I don't remember anything.
"Tell me about the Electric Wave Detector."


class: center, middle name:opening # [FlashR](http://flashx.io/): ### Enable Parallel, Scalable Data Analysis in R
.center[ Da Zheng, Disa Mhembere, Joshua T. Vogelstein, Carey E. Priebe, Randal Burns
Johns Hopkins University
] --- # Goals of FlashR
- Productivity: high-level matrix-oriented programming interface. - Generality: express varieties of machine learning algorithms. - Computation efficiency: comparable to parallel C code. - Scalability: process at least terabytes of data. --- # Motivation
- Big data & data science - Large data volumn: terabytes or petabytes - Complex data analysis: statistics & machine learning - Statistics & machine learning - High computation efficiency - High scalability - High programming productivity --- # Motivation
- Dilemma 1 - High efficiency + high scalability => low-level programming languages (C/C++). - C/C++ => low programming productivity. - Dilemma 2 - Few system programmers know statistics and machine learning well. - Few statisticians and data scientists know C/C++ or parallel programming well. --- class: center, middle .center[ ## Do we have to write parallel C/C++ code to achieve extreme efficiency and scalability? ] --- ## The FlashR solution .center[
] --- ### Challenge #1: achieve generality, efficiency and productivity together.
.center[ ] --- ### Challenge #2: reduce data movement.
.left-pull[ - Speed gap between CPU and RAM increases exponentially in the past decades. - Speed gap between RAM and SSDs remains large. ] .right-pull[ ] --- ## Main programming interface
- Generalized matrix operations. - Vectorized functions to operate on matrix elements. --- ## R base package
- FlashR provides implementations of many matrix functions in the R base package. --- ### Parallelized correlation with 7 lines of native R code
```R corr <- function(D) { n <- nrow(D) D.sum <- rowSums(t(D)) D2.sum <- rowSums(t(D * D)) D.prod <- t(D) %*% D D.mu <- D.sum / n D.sd <- sqrt((D2.sum - n * D.mu * D.mu) / (n - 1)) ret <- (D.prod - n * D.mu %*% t(D.mu)) / (n - 1) / (D.sd %*% t(D.sd)) } ``` --- ### Parallelized k-means with 8 lines of R code
```R kmeans.iter <- function(X, C){ D <- fm.inner.prod(X, t(C), "euclidean", "+") I <- fm.agg.row(D, "which.min") one <- fm.rep.int(1, nrow(I)) CNT <- fm.groupby.row(one, I, "+") C <- fm.groupby.row(X, I, "+") C <- fm.mapply.row(C, CNT, "/") list(C=C, I=I) } ``` --- ### Datasets for performance evaluation
- FlashR vs. R - 65M samples and 32 features - Under a mixture of Gaussian - FlashR vs. Spark Mllib - 1B samples and 32 features - Under a mixture of Gaussian --- ### FlashR outperforms C/FORTRAN code in R with a single thread --- ### FlashR outperforms Spark Mllib by almost an order of magnitude --- ### EM execution of FlashR has little memory consumption --- # Summary
- FlashR is a scalable, efficient programming framework for data analysis. - Next steps: - Upload FlashR to CRAN. - Support other R data structures (e.g., data frame). - Extend a machine learning library. --- # Thank you!
- FlashX: http://flashx.io/ - Get source code: https://github.com/zheng-da/FlashX.git - Email<EMAIL_ADDRESS>- Acknowledgements: This work is graciously supported by DARPA SIMPLEX.


Logout
Login
Dashboard
Result
Pending Actions
Experiment Run Status
Performance and Scale
Operations: List All
Operations: Create
To Do List
User Data
Single Steps
Copy n Create Experiments
Run Experiment
Mask Images
Select Exp, Display Images and Label
Review All Experiments
Home


The JS9 Public API
The JS9 Public API
The JS9 Public API provides a JavaScript programming interface for
interacting with JS9. Obviously, all of JS9 JavaScript code is
available to you within a Web page, but the public API is designed to
stable and well-documented for users and Web designers. It also will
provide the basis for planned language bindings (python, perhaps C/Fortran).
In general, the public API routines act on the current image being
displayed in the default JS9 div element. Since most Web pages will
have only a single JS9 div element, this behavior is usually what you
want. It parallels DS9's behavior in which XPA commands act on the
currently displayed image. For example, to change the colormap of the
current image, use:
JS9.SetColormap("cool");
However, for cases where multiple JS9 div elements are defined on a
single page, you can specify the specific div element to process by
adding an display object argument to the calling sequence with
a single display property:
{display: [div_id]}
where [div_id] is the id of the target JS9 div element. For example,
if two JS9 divs with ids "JS9" and "myJS9", respectively, are present
on a single Web page, you can set the colormap of the second one this way:
JS9.SetColormap("cool", {display: "myJS9"})
Note that this
display object contains only the
display
property and always is specified as the final argument in a call.
The display property can specify an image handle instead of
a JS9 div element id. This is a minor optimization for cases where you want
to call a routine such as JS9.WCSToPix() or JS9.PixtoWCS() many times:
var im = JS9.GetImage({display: "myJS9"});
for(i=0; i<1000; i++){
x = ...
y = ...
wcs = JS9.PixtoWCS(x, y, {display: im});
console.log("%s %s -> %s %s", x, y, wcs.ra, wcs.dec);
}
Passing the image handle will speed up processing very slightly, but
it makes us programmers feel much better.
The optional display object argument is not explicitly
documented in the routines below (except as an example
in JS9.Load()), but it is always available.
Choose from the following sections:
Loading Images
Load an image into JS9
JS9.Load(url, opts, func)
where:
- url: url, fitsy object, in-memory FITS, or FITS blob
- opts: object containing image parameters
- func: optional function to call when image load is complete
Load a FITS file or a PNG representation file into JS9.
You also can pass an in-memory buffer containing a FITS file, or a string
containing a base64-encoded FITS file.
Finally, you can pass a fits object containing the following properties:
- naxis: number of axes in the image
- axis: array of image dimensions for each axis or ...
- naxis[n] image dimensions of each axis (naxis1, naxis2, ...)
- bitpix: FITS bitpix value
- head: object containing header keywords as properties
- image: typed data array containing image data (native format)
- dmin: data min (optional)
- dmax: data max (optional)
The difference between
JS9.RefreshImage() and
JS9.Load() is
that the former updates the data into an existing image, while the latter adds
a completely new image to the display.
To override default image parameters, pass the image opts argument:
href='javascript:JS9.Load("png/m13.png", {scale:"linear", colormap:"sls"});'
If a callback function is specified, it will be called after the image
is loaded:
href='javascript:JS9.Load("fits/3c273.fits", {scale: "linear"}, func);'
The image handle is passed as the first argument to the callback.
To load an image into a specified display, pass the display object as the last argument:
href='javascript:JS9.Load("fits/3c273.fits", {scale: "linear"}, {display: "myJS9"});'
See Displaying Your Data for further discussion of
how to use this routine.
Load an image into a light window or a new (separate) window
JS9.LoadWindow(url, opts, type, html, winopts)
where:
- url: url to load
- opts: optional object containing image parameters and/or the div id
- type: "light" or "new"
- html: html for the new page (default is to display a menubar above the image)
- winopts: for "light", optional dhtml window options
returns:
- id: the id of the JS9 display div
This routine will load an image into a light-weight window or an entirely new
window. The
url and
opts arguments are identical to the standard
JS9.Load() call, except that
opts can contain an
id
string to specify the id of the JS9 div being created. If no id is specified,
a unique id is generated. In either case, the id is returned by the call.
The type argument determines whether to create
a light-weight window or a new (separate) window.
By default, the new window will contain a Menubar above an image display area:

You can use the
html argument to supply different Web page elements
for the window. Furthermore, if you create a light window, a default
set of DynamicDrive dhtmlwindow parameters will be used to make the
window the correct size for the default html:
"width=512px,height=542px,center=1,resize=1,scrolling=1"
You can supply your own parameters for the new dhtmlwindow using the
winOpts argument. See:
DynamicDrive for more information about their light-weight window.
See js9create.html for examples of how to use this routine.
Load one or more images when the Web page is ready
JS9.Preload(url1, opts1, url2, opts2, ... url2, optsn)
where:
- url: url to load
- opts: optional object containing image parameters
This routine will pre-load images into a JS9 display. It can be added
to the Web page body element using the onload() JavaScript call or
called in a JavaScript init routine tied to onload. See index.html and
js9preload.html for examples.
It is worth emphasizing that JS9.Preload() should not be called
until the Web page is fully loaded, since JS9 itself is not fully
initialized until then. It is for this reason that JS9.Preload()
generally is called using an onload routine tied to the Web page body.
Get Load Status
status = JS9.GetLoadStatus(id)
where:
- id: the id of the file that was loaded into JS9
returns:
- status: status of the load
This routine returns the status of the load process for this image. A
status of "complete" means that the image is fully loaded. Other statuses
include:
- loading: the image is in process of loading
- error: image did not load due to an error
- other: another image is loaded into this display
- none: no image is loaded into this display
Thus, to check for image load, one can do this in python:
tfits = "foo.fits"
hdul = fits.open(tfits)
...
j = JS9()
j.SetFITS(hdul, tfits)
while j.GetLoadStatus(tfits) != "complete":
time.sleep(0.1)
j.SetZoom(2)
Working with Images
Get image handle for the current image
im = JS9.GetImage()
returns:
The routine returns the image handle associated with the current image.
The returned image handle can be passed in the display object. This
is marginally more efficient than the default behavior, which is to
determine the current image for each call.
Get image data and auxiliary info for the specified image
imdata = JS9.GetImageData(dflag)
where:
- dflag: specifies whether the data should also be returned
returns:
- imdata: image data object
The image data object contains the following information:
- id: the id of the file that was loaded into JS9
- file: the file or URL that was loaded into JS9
- fits: the FITS file associated with this image
- source: "fits" if a FITS file was downloaded, "fits2png" if a representation file was retrieved
- imtab: "image" for FITS images and png files, "table" for FITS binary tables
- width: x dimension of image
- height: y dimension of image
- bitpix: FITS bits/pixel of each image element (8 for unsigned char, 16, 32 for signed integer, -32 or -64 for float)
- header: JavaScript object containing FITS header values
- data: buffer containing raw data values
This call can return raw data for subsequent use in local analysis
tasks. The format of the returned data depends on the exact value
of
dflag. If
dflag is the boolean value true, an HTML5
typed array is returned. In JavaScript, typed arrays are more
efficient than ordinary JavaScript arrays, and, in this case, the
returned data is actually just reference to the real JS9 image data
(so be careful about changing values).
If dflag is the string "array", a JavaScript array is returned.
This is not a reference to the real data and will utilize
additional memory, but the values can be manipulated safely.
If dflag is the string "base64", a base64-encoded string is
returned. Oddly, this seems to be the fastest method of transferring
data to via socket.io an external process such as Python, and, in fact,
is the method used by the pyjs9.py interface. (The "array" method also can
be used, but seems to be slower.)
The file value can be a FITS file or a representation PNG file. The
fits value will be the path of the FITS file associated with
this image. For a presentation PNG file, the path generally will be
relative to the JS9 install directory. For a normal FITS file, the path
usually is an absolute path to the FITS file.
If you are calling JS9.GetImageData() from an external process (via
the msg protocol), you almost certainly want to set dflag to "array".
Doing so will serialize the data as an array instead of as an object, saving
a considerable amount of transfer data.
Given a FITS-standard 1-indexed image pixel x,y, you can find the data value
at that location using:
val = obj.data[Math.floor(y-0.5) * obj.width + Math.floor(x-0.5)];
Note the need to integerize the x and y values: JavaScript arrays are
objects and so floating point array indices do not get truncated
automatically as in C. They will return null values.
Also note that since we need 0-based data array indexes, we subtract 1 from
the 1-based image position. But then we must add 0.5 before rounding because
by convention, x.0, y.0 is the middle of the pixel.
Display an image
JS9.DisplayImage(step)
where:
- step: starting step to take when displaying the image
The display steps are: "colors" (remake color data when cmap has changed),
"scaled" (rescale data values), "primary" (convert scaled data values
to color values), and "display" (write color values to the Web page).
The default step is "primary", which displays the image without recalculating
color data, scaled data, etc. This generally is what you want, unless you have
explicitly changed parameter(s) used in a prior step.
Re-read the image data and re-display
JS9.RefreshImage(input, func)
where:
- input: object, javascript array, typed array, or FITS blob
- func: optional function to call when image refresh is complete
This routine can be used, for example, in laboratory settings where
data is being gathered in real-time and the JS9 display needs to be
refreshed periodically. The first
input argument can be one of the following:
- a javascript array containing raw data
- a typed array containing raw data
- a blob containing a FITS file
- an object containing a required image property and any of the
following optional properties:
- naxis: number of axes in the image
- axis: array of image dimensions for each axis or ...
- naxis[n]: image dimensions of each axis (naxis1, naxis2, ...)
- bitpix: FITS bitpix value
- head: object containing header keywords as properties
- dmin: data min (optional)
- dmax: data max (optional)
When passing an object as
input, the required
image
property containing the image data can be a javascript array or a
typed data array. It also can contain a base64-encoded string
containing an array. This latter can be useful when calling
JS9.RefreshImage() via HTTP.
Ordinarily, when refreshing an image, there is no need to specify the
optional axis, bitpix, or header properties. But note that you actually
can change these values on the fly, and JS9 will process the new data
correctly. Also, if you do not pass dmin or dmax, they
will be calculated by JS9.
Note that you can pass a blob containing a complete FITS file to this
routine. The blob will be passed to the underlying FITS-handler before
being displayed. Thus, processing time is slightly greater than if you just
pass the image data directly.
The main difference between JS9.RefreshImage()
and JS9.Load() is that the former updates the data into an
existing image, while the latter adds a completely new image to the
display.
Clear the image from the display and mark resources for release
JS9.CloseImage()
Each loaded image claims a non-trivial amount of memory from a finite
amount of browser heap space. For example, the default 32-bit version
of Google Chrome has a memory limit of approximately 500Mb. If you are
finished viewing an image, closing it tells the browser that the
image's memory can be freed. In principle, this is can help reduce
overall memory usage as successive images are loaded and
discarded. Note, however, that closing an image only provides a hint
to the browser, since this sort of garbage collection is not directly
accessible to JavaScript programming.
Some day, all browsers will support full 64-bit addressing and this problem will
go away ...
Get the image colormap
cmap = JS9.GetColormap()
returns:
- cmap: object containing colormap information
The returned cmap object will contain the following properties:
- colormap: colormap name
- contrast: contrast value (range: 0 to 10)
- bias: bias value (range 0 to 1)
Set the image colormap
JS9.SetColormap(colormap, [contrast, bias])
where:
- colormap: colormap name
- contrast: contrast value (range: 0 to 10)
- bias: bias value (range 0 to 1)
Set the current colormap, contrast/bias, or both. This call takes one
(colormap), two (contrast, bias) or three (colormap, contrast, bias)
arguments.
Get the image scale
scale = JS9.GetScale()
returns:
- scale: object containing scale information
The returned scale object will contain the following properties:
- scale: scale name
- scalemin: min value for scaling
- scalemax: max value for scaling
Set the image scale
JS9.SetScale(scale, smin, smax)
where:
- scale: scale name
- smin: scale min value
- smax: scale max value
Set the current scale, min/max, or both. This call takes one
(scale), two (smin, max) or three (scale, smin, smax) arguments.
Get the image zoom factor
zoom = JS9.GetZoom()
returns:
- zoom: floating point zoom factor
Get the zoom factor.
Set the image zoom factor
JS9.SetZoom(zoom)
where:
- zoom: floating or integer zoom factor or zoom directive string
The zoom directives are:
- x[n]|X[n]: multiply the zoom by n (e.g. "x2")
- /[n]: divide the zoom by n (e.g. "/2")
- in|In: zoom in by a factor of two
- out|Out: zoom out by a factor of two
- toFit|ToFit: zoom to fit image in display
Get the image pan position
ipos = JS9.GetPan()
returns:
- ipos: object containing image information for pan
The returned ipos object will contain the following properties:
- x: x image coordinate of center
- y: y image coordinate of center
Set the image pan position
JS9.SetPan(x, y)
where:
- x: x image coordinate
- y: y image coordinate
Set the current pan position using image coordinates.
Note that you can use
JS9.WCSToPix() and
JS9.PixToWCS() to
convert between image and WCS coordinates.
Get the display coordinates from an event
dpos = JS9.EventToDisplayPos(evt)
where:
returns:
- dpos: display position object containing x and y display
coordinate values
If you define your own event callbacks, you can use this routine to convert
the event position to a display position, which can then be used to get the
image position (see below).
Get the image coordinates from the display coordinates
ipos = JS9.DisplayToImagePos(dpos)
where:
- dpos: display position object containing x and y display
coordinate values
returns:
- ipos: image position object containing x and y image
coordinate values
Note that image coordinates are one-indexed, as per FITS conventions, while
display coordinate are 0-indexed.
Get the display coordinates from the image coordinates
dpos = JS9.ImageToDisplayPos(ipos)
where:
- ipos: image position object containing x and y image
coordinate values
returns:
- dpos: display position object containing x and y display
coordinate values
Get display (screen) coordinates from image coordinates. Note that
image coordinates are one-indexed, as per FITS conventions, while
display coordinate are 0-indexed.
Get the image coordinates from the logical coordinates
ipos = JS9.LogicalToImagePos(lpos, lcs)
where:
- lpos: logical position object containing x and y logical
coordinate values
returns:
- ipos: image position object containing x and y image
coordinate values
Logical coordinate systems include: "physical" (defined by LTM/LTV keywords in a
FITS header), "detector" (DTM/DTV keywords), and "amplifier" (ATM/ATV keywords).
Physical coordinates are the most common. In the world of X-ray astronomy, they
refer to the "zoom 1" coordinates of the data file.
This routine will convert from logical to image coordinates. By default, the
current logical coordinate system is used. You can specify a different logical
coordinate system (assuming the appropriate keywords have been defined).
Get the logical coordinates from the image coordinates
lpos = JS9.ImageToLogicalPos(ipos, lcs)
where:
- ipos: image position object containing x and y image
coordinate values
returns:
- lpos: logical position object containing x and y logical
coordinate values
Logical coordinate systems include: "physical" (defined by LTM/LTV keywords in a
FITS header), "detector" (DTM/DTV keywords), and "amplifier" (ATM/ATV keywords).
Physical coordinates are the most common. In the world of X-ray astronomy, they
refer to the "zoom 1" coordinates of the data file.
This routine will convert from image to logical coordinates. By default, the
current logical coordinate system is used. You can specify a different logical
coordinate system (assuming the appropriate keywords have been defined).
Get value/position information
valpos = JS9.GetValPos(ipos, display)
where:
- ipos: image position object containing x and y image coord values
- display: boolean value specifying whether the info box display should be updated (default is true)
returns:
- valpos: value/position object
This routine determines the data value at a given image position
and returns an object containing the following information:
- ix: image x coordinate
- iy: image y coordinate
- isys: image system (i.e. "image")
- px: physical x coordinate
- py: physical y coordinate
- psys: currently selected pixel-based system (i.e. "image"
or "physical") for the above px, py values
- ra: ra in degrees (if WCS is available)
- dec: dec in degrees (if WCS is available)
- wcssys: wcs system (if WCS is available)
- val: floating point pixel value
- val3: pixel value as a string truncated to 3 decimal digits
- vstr: string containing value and position info
- id: id of the image
- file: filename of the image
- object: object name of the image from the FITS header
Get the current WCS units
unitsstr = JS9.GetWCSUnits()
returns:
- unitstr: "pixels", "degrees" or "sexagesimal"
Get the current WCS units.
Set the current WCS units
JS9.SetWCSUnits(unitsstr)
where:
- unitstr: "pixels", "degrees" or "sexagesimal"
Set the current WCS units.
Get the current World Coordinate System
sysstr = JS9.GetWCSSys()
returns:
- sysstr: current World Coordinate System ("FK4", "FK5", "ICRS",
"galactic", "ecliptic", "image", or "physical");
Get current WCS system.
Set the current World Coordinate System
JS9.SetWCSSys(sysstr)
where:
- sysstr: World Coordinate System ("FK4", "FK5", "ICRS",
"galactic", "ecliptic", "image", or "physical")
Set current WCS system. The WCS systems are available only if WCS
information is contained in the FITS header. Also note that "physical"
coordinates are the coordinates tied to the original file. They are
mainly used in X-ray astronomy where individually detected photon
events are binned into an image, possibly using a blocking factor.
For optical images, image and physical coordinate usually are identical.
Convert image pixel position to WCS position
wcsobj = JS9.PixToWCS(x, y)
where:
- x: x image coordinate
- y: y image coordinate
returns:
- wcsobj: world coordinate system object
The wcs object contains the following properties:
- ra: right ascension in floating point degrees
- dec: declination in floating point degrees
- sys: current world coordinate system being used
- str: string of wcs in current system ("[ra] [dec] [sys]")
Convert WCS position to image pixel position
pixobj = JS9.WCSToPix(ra, dec)
where:
- ra: right ascension in floating point degrees
- dec: declination in floating point degrees
returns:
The pixel object contains the following properties:
- x: x image coordinate
- y: y image coordinate
- str: string of pixel values ("[x]" "[y]")
Working with Regions
Spatial regions of interest are a crucial part of astronomical data
analysis. The regions layer is a special case of the more generalized
shape layers, automatically created by JS9 to support the options in
the Regions menu, as well as local and server-side data analysis
using regions.
The regions layer has the special property that, by default,
its z-index is higher than other shape layers, so that regions
are displayed on top of other shape layers.
Note that the GetRegions(), ChangeRegions(), RemoveRegions() calls
all take a regions specification as the second argument, which can be
any of the following (in order of precedence):
- "all": all regions
- [id]: a specific region id returned by JS9.AddRegions()
- "selected": the selected region (or all regions in the selected group)
- [color]: all regions having the specified color (e.g., "red")
- [shape]: all regions having the specified shape (e.g., "circle")
- [tag]: all regions containing the specified tag (e.g., "source")
Thus, it is possible to act on multiple regions at the same time.
Add one or more regions to the regions layer
id = JS9.AddRegions(rarr, opts)
where:
- rarr: a shape string, region object or an array of region objects
- opts: global values to apply to each created region
returns:
- id: id of last region created
The
rarr argument can be a region shape ("annulus", "box",
"circle", "ellipse", "point", "polygon", "text"), a single region
object, or an array of region objects. Region objects contain one or
more properties, of which the most important are:
- shape: "annulus", "box", "circle", "ellipse", "point", "polygon", "text" [REQUIRED]
- x: image x position
- y: image y position
- lcs: object containing logical x, y and sys (e.g. "physical")
- dx: increment from current image x position
- dy: increment from current image y position
- tags: comma separated list of tag strings
- radii: array of radii for annulus region
- width: width for box region
- height: height for box region
- radius: radius value for circle region
- r1: x radius for ellipse region (misnomer noted)
- r2: y radius for ellipse region (misnomer noted)
- pts: array of objects containing x and y positions for polygons
- points: array of objects containing x and y offsets from the center for polygons
- angle: angle in degrees for box and ellipse regions
- color: region color (string name or #rrggbb syntax)
- text: text associated with text region
Other available properties include:
- fixinplace: if true, region cannot be moved or resized
- lockMovementX: region cannot be moved in the x direction
- lockMovementY: region cannot be moved in the y direction
- lockRotation: region cannot be rotated
- lockScalingX: region cannot be resized in the x direction
- lockScalingY: region cannot be resized in the y direction
- fontFamily: font parameter for text region
- fontSize: font parameter for text region
- fontStyle: font parameter for text region
- fontWeight: font parameter for text region
Get information about one or more regions
rarr = JS9.GetRegions(regions)
where:
- regions: which regions to retrieve
returns:
- rarr: array of region objects
Each returned region object contains the following properties:
- id: numeric region id (assigned by JS9 automatically)
- mode: "add", "remove" or "change"
- shape: region shape ("annulus", "box", "circle", "ellipse",
"point", "polygon", "text")
- tags: comma delimited list of region tags (e.g., "source", "include")
- color: region color
- x,y: image coordinates of region
- radii: array of radii for annulus region
- width: width for box region
- height: height for box region
- radius: radius value for circle region
- r1: x radius for ellipse region (misnomer noted)
- r2: y radius for ellipse region (misnomer noted)
- pts: array of objects containing x and y positions, for polygons
- points: array of objects containing x and y offsets from the specified center, for polygons
- angle: angle in degrees for box and ellipse regions
- wcsstr: region string in wcs coordinates
- wcssys: wcs system (e.g. "FK5")
- imstr: region string in image or physical coordinates
- imsys: image system ("image" or "physical")
The image position can be used to access the image data returned by the
JS9.GetImageData() routine:
obj = JS9.GetImageData();
xreg = JS9.GetRegions("selected")[0];
val = obj.data[Math.floor(xreg.y-0.5) * obj.width + Math.floor(xreg.x-0.5)];
Note the need to integerize the x and y values: JavaScript arrays are
objects and so floating point array indices do not get truncated
automatically as in C. They will return null values.
Also note that since we need 0-based data array indexes, we subtract 1 from
the 1-based image position. But then we must add 0.5 before rounding because
by convention, x.0, y.0 is the middle of the pixel.
Change one or more regions
JS9.ChangeRegions(regions, opts)
where:
- regions: which regions to change
- opts: object containing options to change in each region
Change one or more regions. The opts object can contain the parameters
described in the
JS9.AddRegions() section. However, you cannot (yet)
change the shape itself (e.g. from "box" to "circle"). See js9onchange.html
for examples of how to use this routine.
Remove one or more regions from the region layer
JS9.RemoveRegions(regions)
where:
- regions: which regions to remove
Working with Shape Layers
JS9 supports individual layers for drawing 2D graphics. The regions
layer is a special case of a shape layer, created automatically by
JS9. The Catalog plugin creates a separate layer for each catalog.
You can define your own shape layer using the NewShapeLayer()
call and then add geometric shapes to it.
Note that the JS9.GetShapes(), JS9.ChangeShapes(), JS9.RemoveShapes()
calls all take a shape specification as the second argument, which can
be any of the following (in order of precedence):
- "all": all regions
- [id]: a specific region id returned by JS9.AddRegions()
- "selected": the selected region (or all regions in the selected group)
- [color]: all regions having the specified color (e.g., "red")
- [shape]: all regions having the specified shape (e.g., "circle")
- [tag]: all regions containing the specified tag (e.g., "source")
Thus, it is possible to act on multiple shapes at the same time.
Create a new shape layer
lid = JS9.NewShapeLayer(layer, opts)
where:
- layer: name of the layer to create
- opts: default options for this layer
returns:
This routine creates a new named shape layer. You can then, add, change,
and remove shapes in this layer using the routines below. The catalogs
displayed by the Catalog plugin are examples of separate shape layers.
The optional opts parameter allows you to specify default
options for this layer. You can set a default for any property needed
by your shape layer. See JS9.Regions.opts in js9.js for an example of
the default options for the regions layer.
Show or hide the specified shape layer
JS9.ShowShapeLayer(layer, mode)
where:
- layer: name of layer
- mode: true (show layer) or false (hide layer)
Shape layers can be hidden from display. This could be useful, for
example, if you have several catalogs loaded into a display and
want to view one at a time.
Add one or more shapes to the specified layer
JS9.AddShapes(layer, sarr, opts)
where:
- layer: name of layer
- sarr: a shape string, shape object, or an array of shape objects
- opts: global values to apply to each created shape
returns:
- id: id of last shape created
The
sarr argument can be a shape ("annulus", "box",
"circle", "ellipse", "point", "polygon", "text"), a single shape
object, or an array of shape objects. Shape objects contain one or
more properties, of which the most important are:
- shape: "annulus", "box", "circle", "ellipse", "point", "polygon", "text" [REQUIRED]
- x: image x position
- y: image y position
- dx: increment from current image x position
- dy: increment from current image y position
- tags: comma separated list of tag strings
- radii: array of radii for annulus shape
- width: width for box shape
- height: height for box shape
- radius: radius value for circle shape
- r1: x radius for ellipse shape (misnomer noted)
- r2: y radius for ellipse shape (misnomer noted)
- pts: array of objects containing x and y positions, for polygons
- points: array of objects containing x and y offsets from the specified center, for polygons
- angle: angle in degrees for box and ellipse shapes
- color: shape color (string name or #rrggbb syntax)
- text: text associated with text shape
Other available properties include:
- fixinplace: if true, shape cannot be moved or resized
- lockMovementX: shape cannot be moved in the x direction
- lockMovementY: shape cannot be moved in the y direction
- lockRotation: shape cannot be rotated
- lockScalingX: shape cannot be resized in the x direction
- lockScalingY: shape cannot be resized in the y direction
- fontFamily: font parameter for text shape
- fontSize: font parameter for text shape
- fontStyle: font parameter for text shape
- fontWeight: font parameter for text shape
Remove one or more shapes from the specified shape layer
JS9.RemoveShapes(layer, shapes)
where:
- layer: name of layer
- shapes: which shapes to remove
Get information about one or more shapes in the specified shape layer
JS9.GetShapes(layer, shapes)
where:
- layer: name of layer
- shapes: which shapes to retrieve
returns:
- sarr: array of shape objects
Each returned shape object contains the following properties:
- id: numeric region id (assigned by JS9 automatically)
- mode: "add", "remove", or "change"
- shape: region shape ("annulus", "box", "circle", "ellipse",
"point", "polygon", "text")
- tags: comma delimited list of region tags (e.g., "source", "include")
- color: region color
- x,y: image coordinates of region
- size: object containing width and height for box region
- radius: radius value for circle region
- radii: array of radii for annulus region
- eradius: object containing x and y radii for ellipse regions
- pts: array of objects containing x and y positions, for polygons
- angle: angle in degrees for box and ellipse regions
Change one or more shapes in the specified layer
JS9.ChangeShapes(layer, shapes, opts)
where:
- layer: name of layer
- shapes: which shapes to change
- opts: object containing options to change in each shape
Change one or more shapes. The opts object can contain the parameters
described in the
JS9.AddShapes() section. However, you cannot (yet)
change the shape itself (e.g. from "box" to "circle").
Server-side Analysis
Run a simple server-side analysis task
JS9.RunAnalysis(name, parr, func)
where:
- name: name of analysis tool
- parr: optional array of macro-expansion options for command line
- func: optional routine to call when analysis is completed on server
The
JS9.RunAnalysis() routine is used to execute a server-side
analysis task and return the results for further processing within the
Web page.
The optional parr array of parameters is passed to the JS9
analysis macro expander so that values can be added to the command
line. The array is in jQuery name/value serialized object format,
which is described here:
http://api.jquery.com/serializeArray/
func: a function to process the returned data when the task is complete.
The func() routine is a callback function to process the returned
results from the analysis task. The calling sequence is:
func(stdout, stderr, errcode, aobj)
where:
- stdout: a string containing the standard output from the task
- stderr: a string containing the standard error from the task
- errcode: error code value from the task or 0
- aobj: the analysis object from the js9Analysis.json file,
containing, among other things, the important rtype:
"text" or "plot"
Typically, you would check stderr string first and issue an error
message if there is an error. Otherwise, the stdout string can be
processed based on the return type (rtype) property of the output
(e.g., "text" or "plot"). For plotting, you can use flot
functionality already loaded into JS9, or you can use your own chosen
plotting package.
If no func callback is specified, the default processing will
display "text" in a new light window. If the return type is "plot",
the results are assumed to be in flot format and will be plotted.
Run a server-side analysis task, utilizing
parameters in a form
JS9.SubmitAnalysis(el, name, func)
where:
- el: form element (unused at present)
- name: name of analysis tool
- func: optional routine to call when analysis is completed on server
The JS9.SubmitAnalysis() routine is used to run an analysis
task with input parameters from a form. Typically used as
the Run button action in a form, it automatically serializes
the form values and passes them to the JS9 analysis macro expander so
that these values can be integrated into the analysis command line.
See js9analysis.html for a simple example.
The func callback is the same as for JS9.RunAnalysis() above.
Miscellaneous
Print an image
JS9.Print()
Print the currently displayed image. A new window is displayed
containing the image, along with regions and other graphical layers
(the 2D graphics having been converted to a re-scalable format). The
standard Print dialog box also is displayed and can be used to print
this new window. Dismiss both windows when you are finished.
Display help in a light window
JS9.DisplayHelp(name)
where:
- name: name of a help file or url of a Web site to display
The help file names are the property names in JS9.helpOpts (e.g., "user" for
the user page, "install" for the install page, etc.). Alternatively, you can
specify an arbitrary URL to display (just because).
Get location of JS9 installation directory
rpath = JS9.InstallDir(file)
where:
- file: file or directory to convert
returns:
- rpath: path of the file relative to the JS9 install directory
Sometimes a plugin needs to load an auxiliary file inside the plugins
sub-directory. The Web page loading the plugin has an arbitrary
location relative to the JS9 install directory, so this routine
returns a relative path to the js9 install directory.
Send a message to a back-end server
JS9.Send(msg, obj, cb)
where:
- msg: name of the msg, as defined in the back-end server
- obj: object containing msg parameters
- cb: callback to call when back-end server returns its results
JS9 sends various internal messages to the back-end server using either
socket.io protocol (in the Node.js implementation) or CGI. For
example, when a remote analysis call is made, JS9 sends a message to the
back-end server detailing the task to call, parameters to pass, etc. Results
are then returned to JS9 for display. JS9 also sends messages to the
back-end server when a new image is displayed, when a FITS file is to
be converted into a PNG representation file, etc.
Communication with the back-end is usually done behind the scenes and
need not concern users or application programmers. However, if you
write your own socket.io-based server, you might want to add
project-specific messages to your implementation. For example, a
Perl-based or Python-based server might add its own special messages
that execute Perl or Python commands within the server in response to
JS9 messages. In this case, you can use JS9.Send() to send a
message to these message handlers.
The msg name is the name of the message, as defined by the
server. By convention, an object is usually passed to the
message handler. JS9 will add a dataPath property to this
object to indicate the current list of directories in which to
search for data. All other properties are specific to the message being handled.
You can pass a null instead of an object and JS9.Send() will generate
a temporary object to hold the dataPath.
The cb function will be called if the message sends an
acknowledgment. The arguments passed to this function call by the server
are specific to the message being handled.
For example, you can send a message to the back-end server to retrieve the
list of available analysis tasks and then display this list using the call:
JS9.Send("getAnalysis", null, function(s){alert(s)});
The "getAnalysis" message passes no parameters to the server. The
server returns a list of available analysis tasks in JSON format.
Add a JS9 display div and/or associated plugins
JS9.AddDivs(id1, id2, ...)
where:
- id1, id2, ...: optional name(s) of new JS9 display div(s)
You can add new JS9 displays and/or plugins dynamically. To do this, you
create the new divs, add them to the Web page, and then call this routine to
incorporate them into JS9.
The routine will accept a list of JS9 display divs to initialize. If
all you are doing is adding one or more plugins to an existing display,
leave the argument list empty.
For example, to add a new JS9 display and menubar at the end of a Web
page and load an image into that display:
var html = "

";
// jquery append to end of page
$(html).appendTo($("body"));
// create the new JS9 display, with associated plugins
JS9.AddDivs("myJS9");
// just a standard load to that display
JS9.Load("foo.fits", {scale: "log"}, {display: "myJS9"});
See also JS9.LoadWindow() for a nice way to load images into a
light-weight or completely new window.
Prototype Routines (not ready for prime time)
NB: The routines in this section are prototypes and therefore are
subject to change. Feel free to contact us to discuss your needs so
that we can gain a better understanding of is required in these cases.
Load an auxiliary file
JS9.LoadAuxFile(name, func)
where:
- name: class name of auxiliary file to load
- func: function to call once the file is loaded
It sometimes is desirable to process auxiliary files when an image
is first loaded. Examples include overlaying an image mask on an
image, and pre-loading regions from a region file.
The JS9.LoadAuxFile prototypes this sort of functionality.
Auxiliary files are defined in the js9Prefs.json file by means of the
JS9.auxfiles array containing one or more auxfile objects. Each
auxfile specification has the following properties:
- type: type of auxiliary file: currently "mask" or "region"
- name: the class name of the auxiliary file
- image: image (or template) for which this auxfile is valid
- url: URL of the auxfile
For example, the following defines two auxfiles:
"auxFiles": [{"type": "mask",
"name": "sciencemasks",
"image": "casa.*.png",
"url": "../myauxfiles/casa-mask.png"},
{"type": "regions",
"name": "scienceregions",
"image": "casa.*.png",
"url": "../myauxfiles/casa.reg"}],
Here, a mask auxfile and a regions auxfile are defined for Cas-A
dataset(s). These auxfiles are brought into play as follows:
// run this routine after loading each image
function onImageLoad(im){
JS9.LoadAuxFile("sciencemasks", function(im, aux){
// if we succeed in loading the mask, set up the onchange callback
im.onregionschange = regionOnChange;
// view the image through the mask data
im.maskData = aux.im.raw.data;
// I mean now!
im.displayImage("all");
});
JS9.LoadAuxFile("scienceregions");
}
// tell JS9 about the onload callback
JS9.imageOpts.onload = onImageLoad;
An onImageLoad function is defined that will try to load auxfiles of
types "sciencemasks" and "scienceregions". This routine is set to
be called whenever a new image is loaded.
On image load, when JS9.LoadAuxFile() is called, it looks in
the list of known auxfiles for an entry that matches both
the class name and the image name. If found (in the example above,
for Cas-A datasets), the associated auxfile URL is loaded and
type-specific processing is performed:
- masks: the mask file is loaded into the Web page as an
off-screen image and an aux object is created as a property of the
image object. This aux object can be used for subsequent processing
(see below).
- regions: the regions in the region file are created and
displayed on the image.
Once the initial auxfile processing has been performed, the optional
callback function will be called. For the "mask" example above, the
onregionchange property is set to call a JavaScript function (not
shown here) whenever a region changes. The maskData property is set to
point to the raw data of the auxfile (i.e., aux.im.raw.data). Finally,
the image is re-displayed. Setting the maskData property and
redisplaying the image causes the auxfile's data to be displayed as an
opaque overlay on top of the currently displayed image.
As should be clear from the description above, considerable "black
magic" currently is involved when processing auxiliary files.
Visibility is required into the inner properties of the image
object. Please contact us if you want to work with auxiliary files, so
that we can continue to think about what is required for their support.
API Change History
The JS9 Public API is meant to be stable and well-documented. If we are
forced to make an incompatible change to the API, it will be documented here.
20141117: The Set routines now return "OK" instead of true on success
The public Set routines (SetZoom(), SetColormap(), etc)
were returning a boolean true when successful. This has been changed
to "OK", to make it clear that the return value is a status value,
not a boolean data value.
20141028: callback function to RunAnalysis and SubmitAnalysis
Due to an oversight, the signature of the callback function supplied to
RunAnalysis() (and its derivative function,
SubmitAnalysis()) was missing the errcode argument.
To correct this mistake, the signature was changed from:
func(stdout, stderr, aobj)
to:
func(stdout, stderr, errcode, aobj)
See js9onchange.html for an example of using this callback function.
Last updated: November 14, 2014


This page allows you to view and set the mail sender details for messages sent from this mailbox.
If you have multiple email addresses and want to send mail with the sender details (From: field etc) set to an alternate address you can do so using this page.
Enter the email address from which the mail will appear to have been sent, the Full Name from which it will be sent, and the Reply-To address, then click OK.
Any email sent while that mailbox is open will have the details you entered. Mail sent from other mailboxes, CIX topic, or newsgroups will be unaffected.
Please note that the default values for your mailboxes can be set from the Internet page of the Mail dialog from the Settings menu.


Design pattern status
Evidence required to make or change a design pattern.
One quarter
EXPERIMENTAL
LIKELY TO CHANGE
TRIED AND TESTED
GOV.UK Elements
Tested with users in single service
under discussion
Easy and quick to reuse, 100+ hours of usability testing, used in multiple service
Page patterns
something
under discussion
Easy and quick to reuse, included in prototyping kit
Content patterns
something
under discussion
Easy and quick to reuse,
Larger patterns
Repeated need across government, included in multiple services in Alpha and Beta
discussion
Easy and quick to reuse,
used in multiple Live services,
data showing it saves users time,
data showing it save money across government


Coming Soon
Alok and MacBook M1 are currently working hard building this page!
Check my LinkedIn instead


Getting Started with Wyze SDK¶
A modern Python client for controlling Wyze devices.
Whether you’re building a custom app, or integrating into a third-party service like Home Assistant, Wyze Developer Kit for Python allows you to leverage the flexibility of Python to get your project up and running as quickly as possible.
Feature |
What its for |
Package |
Web Client |
Send data to or query data from Wyze using a variety of device-specific sub-clients. |
|
Bulb Client |
Control Wyze Bulb and Wyze Bulb Color |
|
Entry Sensor Client |
Interact with Wyze Sense Entry Sensors |
|
Camera Client |
Control Wyze Cameras |
|
Event Client |
Manage Wyze alarm events |
|
Lock Client |
Control Wyze Lock |
|
Motion Sensor Client |
Interact with Wyze Sense Motion Sensors |
|
Plug Client |
Control Wyze Plug and Wyze Plug Outdoor |
|
Scale Client |
Control Wyze Scale |
|
Thermostat Client |
Control Wyze Thermostat |
|
Vacuum Client |
Control Wyze Robot Vacuum |
|
Request Signature Verification |
Sign outgoing requests for the Wyze API servers. |
|
Models |
Pythonic class objects to model Wyze devices. |
|
Disclaimer: This repository is for non-destructive use only. WyzeLabs is a wonderful company providing excellent devices at a reasonable price. I ask that you do no harm and be civilized.
As this repository is entirely reverse-engineered, it may break at any time. If it does, I will fix it to the best of my ability.
Installation¶
This package supports Python 3.8 and higher. I recommend using PyPI to install Wyze SDK
pip install wyze_sdk
Of course, you can always pull the source code directly into your project:
git clone https://github.com/shauntarves/wyze-sdk.git
And then, save a few lines of code as ./test.py
.
# test.py
import sys
# Load the local source directly
sys.path.insert(1, "./wyze-sdk")
# Enable debug logging
import logging
logging.basicConfig(level=logging.DEBUG)
# Verify it works
import os
from wyze_sdk import Client
client = Client(email=os.environ['WYZE_EMAIL'], password=os.environ['WYZE_PASSWORD'])
api_response = client.api_test()
You can run the code this way.
python test.py
Getting Help¶
If you get stuck, I’m here to help. The following are the best ways to get assistance working through your issue:
GitHub Issue Tracker for questions, feature requests, bug reports and general discussion related to this package.


The CpuLoad class (org.bhavaya.util) provides load information for the system's processor(s). The class uses a native c compiled program to access the machine's resources.
The class can be seen in action by running the demo directly using JavaWebStart, from the source code, or if you have downloaded and extracted examples.zip it can be run with: ant cpuloaddemo. A screen shot of the CPU Load Demo is shown below.
CpuLoad is a singleton class, with two methods for accessing load information:
System.out.println("Load = " + CpuLoad.getInstance().getLoad()*100.0 + "%"); System.out.println("Average Load = " + CpuLoad.getInstance().getLoadAverage()*100 + "%");
When using this component, it is necessary to ensure that the VM knows the location of the native library, by using an appropriately modified command line argument (see library error) similar to:
-Djava.library.path="C:/extract/location/bhavaya/lib"
(Also remember to add Bhavaya's jar files to your classpath (extract_location/bhavaya/bin/bhavaya.jar and extract_location/bhavaya/lib/log4j-1.2.15-patched.jar).)


[1]
Nice clean rooms thus giving The hotel was just okay but adequate.
[2]
Nice clean rooms decent bathroom constantly fell in sink from it 's holder when anyone used The hotel was just okay but adequate.