Skip to content

Commit

Permalink
Merge branch 'traits'
Browse files Browse the repository at this point in the history
Conflicts:
	src/CameraImage.py
  • Loading branch information
ptomato committed Jul 25, 2012
2 parents 4276a1b + 6486b00 commit 2ae5a04
Show file tree
Hide file tree
Showing 31 changed files with 1,270 additions and 1,662 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
_site
awesome.css
766 changes: 0 additions & 766 deletions data/Beams.ui

This file was deleted.

29 changes: 0 additions & 29 deletions data/menus.xml

This file was deleted.

Binary file added icons/camera-photo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added icons/camera-video.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added icons/gtk-quit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added icons/stock_about.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added icons/stock_properties.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added icons/stock_save.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions src/AcquisitionThread.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import threading
import time


class AcquisitionThread(threading.Thread):

def __init__(self, camera, queue):
super(AcquisitionThread, self).__init__()
self.abort_flag = False
self.camera = camera
self.queue = queue

def run(self):
while not self.abort_flag:
self.camera.query_frame()
self.queue.put(self.camera.frame, block=False)
time.sleep(0)
90 changes: 54 additions & 36 deletions src/ApogeeCam.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,57 @@
# generate and import apogee ActiveX module
win32com.client.gencache.EnsureModule('{A2882C73-7CFB-11D4-9155-0060676644C1}', 0, 1, 0)
from win32com.client import constants as Constants
from traits.api import Str, Int, Enum, Float, Bool
from traitsui.api import View, Item

from Camera import Camera, CameraError

_interface_constants = {
'usb': Constants.Apn_Interface_USB,
'net': Constants.Apn_Interface_NET}
_reverse_constants = dict((v, k) for k, v in _interface_constants.iteritems())

from Camera import *

class ApogeeCam(Camera):
'''Apogee Alta or Ascent camera'''

def __init__(self, interface='usb', *args, **kwargs):
Camera.__init__(self, *args, **kwargs)

camera_num2 = Int(0)
camera_model = Str()
driver_version = Str()
interface = Enum('usb', 'net')
expose_time = Float(0.05)
open_shutter = Bool(True)

view = View(
Item('interface'),
Item('camera_number'),
Item('camera_num2'),
Item('expose_time'),
Item('open_shutter'))

def __init__(self, **traits):
super(ApogeeCam, self).__init__(camera_number=0, **traits)
self._cam = win32com.client.Dispatch('Apogee.Camera2')
if interface == 'usb':
self._interface = Constants.Apn_Interface_USB
elif interface == 'net':
self._interface = Constants.Apn_Interface_NET
else:
raise ValueError('Invalid value "{0}" for interface; use "usb" or "net"'.format(interface))
self._camera_num2 = 0
self._buffer = None

def open(self):
self._cam.Init(self._interface, self.camera_number, self._camera_num2, 0)
self._cam.Init(_interface_constants[self.interface], self.camera_number,
self.camera_num2, 0)
self._buffer = N.zeros(self.roi[-1:-3:-1], dtype=N.uint16)

def close(self):
self._cam.Close()

def query_frame(self, expose_time=0.05, open_shutter=True):

def query_frame(self, expose_time=None, open_shutter=None):
"""
Start an exposure and wait for it to finish.
Pass @expose_time or @open_shutter to override the camera object's
default parameters.
"""
if expose_time is None:
expose_time = self.expose_time
if open_shutter is None:
open_shutter = self.open_shutter
try:
self._cam.Expose(expose_time, open_shutter)
while self._cam.ImagingStatus != Constants.Apn_Status_ImageReady:
Expand All @@ -38,54 +63,47 @@ def query_frame(self, expose_time=0.05, open_shutter=True):
if self._cam.ImagingStatus < 0:
self.reset()
self.frame = N.copy(self._buffer)

def choose_camera(self):
discover = win32com.client.Dispatch('Apogee.CamDiscover')
discover.DlgCheckUsb = True
discover.ShowDialog(True)
if not discover.ValidSelection:
raise ValueError('No camera selected')
self._interface = discover.SelectedInterface
self.interface = _reverse_constants[discover.SelectedInterface]
self.camera_number = discover.SelectedCamIdOne
self._camera_num2 = discover.SelectedCamIdTwo
self.camera_num2 = discover.SelectedCamIdTwo

def reset(self):
self._cam.ResetState()
# if error status persists, raise an exception
if self._cam.ImagingStatus < 0:
raise CameraError('Error not cleared by reset', self.camera_number)

@property
def resolution(self):

def _resolution_default(self):
return self._cam.ImagingColumns, self._cam.ImagingRows

@property
def camera_model(self):

def _camera_model_default(self):
return self._cam.CameraModel

@property
def driver_version(self):

def _driver_version_default(self):
return self._cam.DriverVersion

@property
def id_string(self):
def _id_string_default(self):
return 'Apogee {} Driver version: {}'.format(
self.camera_model,
self.driver_version)

@property
def roi(self):
def _roi_default(self):
return (self._cam.RoiStartX,
self._cam.RoiStartY,
self._cam.RoiPixelsH,
self._cam.RoiPixelsV)

@roi.setter
def roi(self, value):
def _roi_changed(self, value):
x, y, w, h = value
self._cam.RoiStartX = x
self._cam.RoiStartY = y
self._cam.RoiPixelsH = w
self._cam.RoiPixelsV = h
self._buffer = N.zeros((h, w), dtype=N.uint16)

54 changes: 32 additions & 22 deletions src/AwesomeColorMaps.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,59 @@
import numpy as N
import matplotlib.colors
from chaco.api import ColorMapper

def rotate(x, y, angle):
r, theta = N.sqrt(x ** 2 + y ** 2), N.arctan2(y, x)

def _rotate(x, y, angle):
r, theta = N.hypot(x, y), N.arctan2(y, x)
theta += angle
return r * (N.cos(theta), N.sin(theta))

def luminance_colormap(num_cycles=2, num_colors=256, reverse=False):
'''
Returns a Matplotlib color scale that cycles through the hues @num_cycles
times, while maintaining monotonic luminance (i.e., if it is printed in
black and white, then it will be perceptually equal to a linear grayscale.

def isoluminant(rng, num_cycles=1, num_colors=256, reverse=False, **traits):
"""
Generator function for a Chaco color scale that cycles through the hues
@num_cycles times, while maintaining monotonic luminance (i.e., if it is
printed in black and white, then it will be perceptually equal to a linear
grayscale.
Ported from the Matlab(R) code from: McNames, J. (2006). An effective color
scale for simultaneous color and gray-scale publications. IEEE Signal
Processing Magazine 23(1), 82--87.
'''
"""

# Triangular window function
window = N.sqrt(3.0) / 8.0 * N.bartlett(num_colors)

# Independent variable
t = N.linspace(N.sqrt(3.0), 0.0, num_colors)

# Initial values
operand = (t - N.sqrt(3.0) / 2.0) * num_cycles * 2.0 * N.pi / N.sqrt(3.0)
r0 = t
g0 = window * N.cos(operand)
b0 = window * N.sin(operand)

# Convert RG to polar, rotate, and convert back
r1, g1 = rotate(r0, g0, N.arcsin(1.0 / N.sqrt(3.0)))
r1, g1 = _rotate(r0, g0, N.arcsin(1.0 / N.sqrt(3.0)))
b1 = b0

# Convert RB to polar, rotate, and convert back
r2, b2 = rotate(r1, b1, N.pi / 4.0)
r2, b2 = _rotate(r1, b1, N.pi / 4.0)
g2 = g1

# Ensure finite precision effects don't exceed unit cube boundaries
r = r2.clip(0.0, 1.0)
g = g2.clip(0.0, 1.0)
b = b2.clip(0.0, 1.0)

the_map = N.vstack((r, g, b)).T
return matplotlib.colors.ListedColormap(the_map[::-1 if reverse else 1])
return ColorMapper.from_palette_array(the_map[::-1 if reverse else 1],
range=rng, **traits)


awesome = matplotlib.colors.ListedColormap(N.loadtxt('../data/awesomecolormap.csv', delimiter=','))
isoluminant = luminance_colormap()
def awesome(rng, **traits):
"""
Generator function for a Chaco color scale that has low-intensity contrast.
"""
return ColorMapper.from_palette_array(
N.loadtxt('../data/awesomecolormap.csv', delimiter=','),
range=rng, **traits)
34 changes: 34 additions & 0 deletions src/BackgroundSubtract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#coding: utf8
import numpy as N
from traits.api import Button
from traitsui.api import View, VGroup, Item
from TransformPlugin import TransformPlugin


class BackgroundSubtract(TransformPlugin):

capture_background = Button()

view = View(
VGroup(
Item('active'),
Item('capture_background', show_label=False),
label='Background Subtract',
show_border=True))

def __init__(self, **traits):
super(BackgroundSubtract, self).__init__(**traits)
self._background_frame = None
self._capture_next_frame = True

def _process(self, frame):
if self._capture_next_frame:
self._background_frame = frame
self._capture_next_frame = False
temp = N.asfarray(frame) - self._background_frame
if frame.dtype.kind == 'u':
temp[temp < 0] = 0.0
return N.asarray(temp, dtype=frame.dtype)

def _capture_background_fired(self):
self._capture_next_frame = True
Loading

0 comments on commit 2ae5a04

Please sign in to comment.