|
From: <ah...@us...> - 2011-11-17 10:26:56
|
Revision: 701
http://pyphant.svn.sourceforge.net/pyphant/?rev=701&view=rev
Author: aheld84
Date: 2011-11-17 10:26:46 +0000 (Thu, 17 Nov 2011)
Log Message:
-----------
Merge branch 'master' into svn-trunk
* master: (24 commits)
Fix: CommentChar in FMFLoader
Fix for ;/# error in FMFLoader - see #52
Fix for #/; error in FMFLoader - see #52
Fix: Pathological fmf tables
Fix: Unique timestamps
Fix: Bin centers of Histogram worker
Enh: Addes simple instantiation tests for tools and OSC
Enh: Added tests for ImageProcessing toolbox
Enh: Added / updated ImageProcessing tests
Enh: Added test for thresholding with units
Enh: Added simple LoadZStack worker
Fix: Logical Operators for SampleContainers
Enh: Adopted tests for intended logical operators
Fix: Removed unnecessary imports from DataContainer
Enh: Added optional unit support to ThresholdingWorker
Enh: Changed deprecated interpretation of multi dim images
Cosm: Changed display name of some workers
Fix: Broken import in InvertWorker
Cosm: Cleaned up OscMapper.py
Fix: wxPyphant crash upon exit
...
Modified Paths:
--------------
trunk/src/pyphant/pyphant/core/CompositeWorker.py
trunk/src/pyphant/pyphant/core/DataContainer.py
trunk/src/pyphant/pyphant/core/Helpers.py
trunk/src/pyphant/pyphant/tests/TestDataContainer.py
trunk/src/pyphant/pyphant/wxgui2/wxPyphantApplication.py
trunk/src/workers/ImageProcessing/ImageProcessing/EnhanceContrast.py
trunk/src/workers/ImageProcessing/ImageProcessing/FitBackground.py
trunk/src/workers/ImageProcessing/ImageProcessing/InvertWorker.py
trunk/src/workers/ImageProcessing/ImageProcessing/Medianiser.py
trunk/src/workers/ImageProcessing/ImageProcessing/ThresholdingWorker.py
trunk/src/workers/ImageProcessing/ImageProcessing/Watershed.py
trunk/src/workers/ImageProcessing/ImageProcessing/__init__.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestAutoFocus.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestThresholdingWorker.py
trunk/src/workers/OSC/OSC/OscMapper.py
trunk/src/workers/OSC/OSC/__init__.py
trunk/src/workers/OSC/OSC/tests/TestMRA.py
trunk/src/workers/Statistics/Statistics/Histogram.py
trunk/src/workers/Statistics/Statistics/tests/TestHistogram.py
trunk/src/workers/fmfile/fmfile/FMFLoader.py
trunk/src/workers/fmfile/fmfile/tests/TestFMFLoader.py
trunk/src/workers/tools/tools/__init__.py
Added Paths:
-----------
trunk/src/pyphant/pyphant/core/AstTransformers.py
trunk/src/pyphant/pyphant/tests/TestTimestamp.py
trunk/src/workers/ImageProcessing/ImageProcessing/LoadZStack.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestCoverage.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestDiffWorker.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestETFR.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestEdgeFill.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestEnhanceContrast.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestFitBackground.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestGradient.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestInvert.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestLocalExtrema.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestUltimatePoints.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestWatershed.py
trunk/src/workers/OSC/OSC/MRA.py
trunk/src/workers/OSC/OSC/tests/TestInstantiation.py
trunk/src/workers/fmfile/fmfile/tests/resources/fmf/hash_test.fmf
trunk/src/workers/fmfile/fmfile/tests/resources/fmf/multitable.fmf
trunk/src/workers/fmfile/fmfile/tests/resources/fmf/onecolumn.fmf
trunk/src/workers/fmfile/fmfile/tests/resources/fmf/onerow.fmf
trunk/src/workers/fmfile/fmfile/tests/resources/fmf/onerow_dep.fmf
trunk/src/workers/fmfile/fmfile/tests/resources/fmf/onevalue.fmf
trunk/src/workers/fmfile/fmfile/tests/resources/fmf/semi_test.fmf
trunk/src/workers/tools/tools/tests/TestInstantiation.py
Removed Paths:
-------------
trunk/src/workers/ImageProcessing/ImageProcessing/NDImageWorker.py
trunk/src/workers/tools/tools/MRA.py
Added: trunk/src/pyphant/pyphant/core/AstTransformers.py
===================================================================
--- trunk/src/pyphant/pyphant/core/AstTransformers.py (rev 0)
+++ trunk/src/pyphant/pyphant/core/AstTransformers.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -0,0 +1,211 @@
+from pyphant.quantities import Quantity
+from ast import (NodeTransformer, fix_missing_locations, Name, Load,
+ BinOp, Num, Mult, Compare, BoolOp, And, Add, Sub, Div, Or,
+ Call, Not, Expression)
+
+
+class LocationFixingNodeTransformer(NodeTransformer):
+ def visit(self, *args, **kargs):
+ result = NodeTransformer.visit(self, *args, **kargs)
+ fix_missing_locations(result)
+ return result
+
+
+class ReplaceName(LocationFixingNodeTransformer):
+ def __init__(self, sampleContainer):
+ self.localDict = {}
+ self.count = 0
+ self.sc = sampleContainer
+
+ def visit_Call(self, node):
+ if isinstance(node.func, Name) and node.func.id.lower() == 'col':
+ newName = self.getName(self.sc[node.args[0].s])
+ return Name(newName, Load())
+
+ def visit_Str(self, node):
+ quantity = Quantity(node.s)
+ class QuantityDummy(object):
+ pass
+ dummy = QuantityDummy()
+ dummy.unit = Quantity(1.0, quantity.unit)
+ dummy.data = quantity.value
+ dummy.dimensions = None
+ newName = self.getName(dummy)
+ return Name(newName, Load())
+
+ def getName(self, ref):
+ newName = "N%s" % self.count
+ self.count += 1
+ self.localDict[newName] = ref
+ return newName
+
+
+def withFactor(factor, node):
+ if not isinstance(factor, float):
+ raise ValueError('Incompatible units!')
+ if factor == 1.0:
+ return node
+ return BinOp(Num(factor), Mult(), node)
+
+
+class ReplaceCompare(LocationFixingNodeTransformer):
+ def __init__(self, localDict):
+ self.localDict = localDict
+
+ def visit_Compare(self, node):
+ self.generic_visit(node)
+ unitcalc = UnitCalculator(self.localDict)
+ leftUD = unitcalc.getUnitAndDim(node.left)
+ listUD = [unitcalc.getUnitAndDim(comp) for comp in node.comparators]
+ nonNoneDims = [ud[1] for ud in listUD + [leftUD] if ud[1] is not None]
+ for dims in nonNoneDims:
+ checkDimensions(nonNoneDims[0], dims)
+ factorlist = [ud[0] / leftUD[0] for ud in listUD]
+ newComplist = [withFactor(*t) \
+ for t in zip(factorlist, node.comparators)]
+ compOp = Compare(node.left, node.ops, newComplist)
+ compOpTrans = self.compBreaker(compOp)
+ return compOpTrans
+
+ def compBreaker(self, node):
+ assert isinstance(node, Compare)
+ if len(node.comparators) == 1:
+ return node
+ else:
+ comp1 = Compare(node.left, node.ops[0:1],
+ node.comparators[0:1])
+ comp2 = Compare(node.comparators[0],
+ node.ops[1:], node.comparators[1:])
+ newNode = BoolOp(And(), [comp1, self.compBreaker(comp2)])
+ return newNode
+
+
+class ReplaceOperator(LocationFixingNodeTransformer):
+ def __init__(self, localDict):
+ self.localDict = localDict
+
+ def visit_BinOp(self, node):
+ self.generic_visit(node)
+ unitcalc = UnitCalculator(self.localDict)
+ leftUD = unitcalc.getUnitAndDim(node.left)
+ rightUD = unitcalc.getUnitAndDim(node.right)
+ checkDimensions(leftUD[1], rightUD[1])
+ if isinstance(node.op, (Add, Sub)):
+ factor = rightUD[0] / leftUD[0]
+ right = withFactor(factor, node.right)
+ binOp = BinOp(node.left, node.op, right)
+ return binOp
+ elif isinstance(node.op, (Mult, Div)):
+ return node
+ else:
+ raise NotImplementedError('%s not implemented' % (node.op, ))
+
+ def visit_BoolOp(self, node):
+ self.generic_visit(node)
+ if isinstance(node.op, And):
+ func = 'logical_and'
+ elif isinstance(node.op, Or):
+ func = 'logical_or'
+ else:
+ raise NotImplementedError('%s not implemented' % (node.op, ))
+ return self.boolOpBreaker(node.values, func)
+
+ def boolOpBreaker(self, values, func):
+ if len(values) == 1:
+ return values[0]
+ else:
+ return Call(Name(func, Load()),
+ [values[0], self.boolOpBreaker(values[1:], func)],
+ [], None, None)
+
+ def visit_UnaryOp(self, node):
+ self.generic_visit(node)
+ if isinstance(node.op, Not):
+ return Call(Name('logical_not', Load()), [node.operand],
+ [], None, None)
+ else:
+ raise NotImplementedError('%s not implemented' % (node.op, ))
+
+
+class UnitCalculator(object):
+ def __init__(self, localDict):
+ self.localDict = localDict
+
+ def getUnitAndDim(self, node):
+ if isinstance(node, Expression):
+ return self.getUnitAndDim(node.body)
+ elif isinstance(node, Name):
+ if node.id in ['True', 'False']:
+ return (1.0, None)
+ else:
+ column = self.localDict[node.id]
+ return (column.unit, column.dimensions)
+ elif isinstance(node, Num):
+ return (1.0, None)
+ elif isinstance(node, Call):
+ if not isinstance(node.func, Name):
+ raise NotImplementedError(
+ 'Dynamic functions are not implemented!')
+ funcId = node.func.id
+ if funcId in ['logical_and', 'logical_or']:
+ left = self.getUnitAndDim(node.args[0])
+ right = self.getUnitAndDim(node.args[1])
+ dimensions = checkDimensions(left[1], right[1])
+ if not isinstance(left[0], float):
+ raise ValueError(
+ "Type %s cannot be interpreted as a Boolean" % left)
+ if not isinstance(right[0], float):
+ raise ValueError(
+ "Type %s cannot be interpreted as a Boolean" % right)
+ return (1.0, dimensions)
+ elif funcId == 'logical_not':
+ return self.getUnitAndDim(node.args[0])
+ else:
+ raise NotImplementedError("Function '%s' not implemented" \
+ % (funcId, ))
+ elif isinstance(node, BinOp):
+ left = self.getUnitAndDim(node.left)
+ right = self.getUnitAndDim(node.right)
+ dimensions = checkDimensions(left[1], right[1])
+ if isinstance(node.op, (Add, Sub)):
+ if not isinstance(left[0] / right[0], float):
+ raise ValueError("units %s, %s not compatible" \
+ % (left, right))
+ unit = left[0]
+ elif isinstance(node.op, Mult):
+ unit = left[0] * right[0]
+ elif isinstance(node.op, Div):
+ unit = left[0] / right[0]
+ else:
+ raise NotImplementedError()
+ return (unit, dimensions)
+ elif isinstance(node, Compare):
+ left = self.getUnitAndDim(node.left)
+ nonNoneDims = []
+ if left[1] is not None:
+ nonNoneDims.append(left[1])
+ for comparator in node.comparators:
+ right = self.getUnitAndDim(comparator)
+ if right[1] is not None:
+ nonNoneDims.append(right[1])
+ if not isinstance(left[0] / right[0], float):
+ raise ValueError("units %s, %s not compatible" \
+ % (left[0], right[0]))
+ if len(nonNoneDims) >= 1:
+ for dims in nonNoneDims:
+ checkDimensions(nonNoneDims[0], dims)
+ dimensions = nonNoneDims[0]
+ else:
+ dimensions = None
+ return (1.0, dimensions)
+ else:
+ raise NotImplementedError()
+
+
+def checkDimensions(dimensions1, dimensions2):
+ if dimensions1 is not None and dimensions2 is not None and \
+ dimensions1 != dimensions2:
+ msg = 'Dimensions "%s" and "%s" do not match!' \
+ % (dimensions1, dimensions2)
+ raise ValueError(msg)
+ return dimensions1 or dimensions2
Modified: trunk/src/pyphant/pyphant/core/CompositeWorker.py
===================================================================
--- trunk/src/pyphant/pyphant/core/CompositeWorker.py 2011-05-23 12:48:36 UTC (rev 700)
+++ trunk/src/pyphant/pyphant/core/CompositeWorker.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -84,7 +84,7 @@
API = 2
VERSION = 1
REVISION = "$Revision: $"[11:-1]
- name = "CompositeWorker"
+ name = "Composite"
_params = [("noSockets", "Number of sockets", 0, None),
("noPlugs", "Number of plugs", 0, None)]
Modified: trunk/src/pyphant/pyphant/core/DataContainer.py
===================================================================
--- trunk/src/pyphant/pyphant/core/DataContainer.py 2011-05-23 12:48:36 UTC (rev 700)
+++ trunk/src/pyphant/pyphant/core/DataContainer.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -70,10 +70,11 @@
__version__ = "$Revision$"
import copy, hashlib, threading, numpy, StringIO
-import os, platform, datetime, socket, urlparse
-from pyphant.quantities import (isQuantity, Quantity)
+import urlparse
+from pyphant.core.AstTransformers import (
+ ReplaceName, ReplaceCompare, ReplaceOperator, UnitCalculator,
+ checkDimensions)
import Helpers
-from ast import (NodeTransformer, NodeVisitor)
import logging
_logger = logging.getLogger("pyphant")
@@ -175,7 +176,7 @@
self.id = id
else:
self.hash = self.generateHash()
- self.timestamp = datetime.datetime.utcnow()
+ self.timestamp = Helpers.getModuleUniqueTimestamp()
self.id = u"emd5://%s/%s/%s/%s.%s" % (self.machine,
self.creator,
enc(self.timestamp.isoformat('_')),
@@ -336,15 +337,15 @@
sorted by precedence from lowest precedence (least binding) to highest
precedence (most binding):
+ or
+ and
+ not
Comparisons: <, <=, >, >=, <>, !=, ==
- Bitwise OR: |
- Bitwise XOR: ^
- Bitwise AND: &
Addition and Subtraction: +, -
Multiplication, Division: *, /
- Positive, Negative, Bitwise NOT: +x, -x, ~x
+ Positive, Negative: +x, -x
- Not implemented: and, or, not, **, //, %, if - else
+ Not implemented: ~, &, |, **, //, %, <<, >>
Examples
--------
@@ -362,7 +363,7 @@
exprStr = "col('Distance') / col('Time')"
exprStr = "col('Distance') - '1 m'"
exprStr = "col('t') >= '4 s'"
- exprStr = "(col('s') > '1 m') & (COL('Time') == '3s')"
+ exprStr = "col('s') > '1 m' and COL('Time') == '3s'"
"""
exprStr = exprStr or 'True'
@@ -370,10 +371,16 @@
rpn = ReplaceName(self)
expr = compile(exprStr, "<calcColumn>", 'eval', ast.PyCF_ONLY_AST)
replacedExpr = rpn.visit(expr)
+ rpc = ReplaceCompare(rpn.localDict)
+ factorExpr = rpc.visit(replacedExpr)
rpo = ReplaceOperator(rpn.localDict)
- factorExpr = rpo.visit(replacedExpr)
+ factorExpr = rpo.visit(factorExpr)
localDict = dict([(key, value.data) \
for key, value in rpn.localDict.iteritems()])
+ numpyDict = {'logical_and':numpy.logical_and,
+ 'logical_or':numpy.logical_or,
+ 'logical_not':numpy.logical_not}
+ localDict.update(numpyDict)
data = eval(compile(factorExpr, '<calcColumn>', 'eval'), {}, localDict)
unitcalc = UnitCalculator(rpn.localDict)
unit, dims = unitcalc.getUnitAndDim(replacedExpr)
@@ -465,179 +472,3 @@
return True
else:
raise AssertionError, diagnosis.getvalue()
-
-
-class LocationFixingNodeTransformer(NodeTransformer):
- def visit(self, *args, **kargs):
- result = NodeTransformer.visit(self, *args, **kargs)
- from ast import fix_missing_locations
- fix_missing_locations(result)
- return result
-
-
-class ReplaceName(LocationFixingNodeTransformer):
- def __init__(self, sampleContainer):
- self.localDict = {}
- self.count = 0
- self.sc = sampleContainer
-
- def visit_Call(self, node):
- from ast import (Name, Load)
- if isinstance(node.func, Name) and node.func.id.lower() == 'col':
- newName = self.getName(self.sc[node.args[0].s])
- return Name(newName, Load())
-
- def visit_Str(self, node):
- from ast import (Name, Load)
- quantity = Quantity(node.s)
- class QuantityDummy(object):
- pass
- dummy = QuantityDummy()
- dummy.unit = Quantity(1.0, quantity.unit)
- dummy.data = quantity.value
- dummy.dimensions = None
- newName = self.getName(dummy)
- return Name(newName, Load())
-
- def getName(self, ref):
- newName = "N%s" % self.count
- self.count += 1
- self.localDict[newName] = ref
- return newName
-
-
-class ReplaceOperator(LocationFixingNodeTransformer):
- def __init__(self, localDict):
- self.localDict = localDict
-
- def visit_BinOp(self, node):
- from ast import (Add, Sub, BinOp)
- self.generic_visit(node)
- unitcalc = UnitCalculator(self.localDict)
- leftUD = unitcalc.getUnitAndDim(node.left)
- rightUD = unitcalc.getUnitAndDim(node.right)
- checkDimensions(leftUD[1], rightUD[1])
- if isinstance(node.op,(Add, Sub)):
- factor = rightUD[0] / leftUD[0]
- right = self.withFactor(factor, node.right)
- binOp = BinOp(node.left, node.op, right)
- return binOp
- else:
- return node
-
- def visit_Compare(self, node):
- from ast import Compare
- self.generic_visit(node)
- unitcalc = UnitCalculator(self.localDict)
- leftUD = unitcalc.getUnitAndDim(node.left)
- listUD = [unitcalc.getUnitAndDim(comp) for comp in node.comparators]
- nonNoneDims = [ud[1] for ud in listUD + [leftUD] if ud[1] is not None]
- for dims in nonNoneDims:
- checkDimensions(nonNoneDims[0], dims)
- factorlist = [ud[0] / leftUD[0] for ud in listUD]
- newComplist = [self.withFactor(*t) \
- for t in zip(factorlist, node.comparators)]
- compOp = Compare(node.left, node.ops, newComplist)
- compOpTrans = self.compBreaker(compOp)
- return compOpTrans
-
- def withFactor(self, factor, node):
- from ast import (BinOp, Num, Mult)
- if not isinstance(factor, float):
- raise ValueError('Incompatible units!')
- if factor == 1.0:
- return node
- return BinOp(Num(factor), Mult(), node)
-
- def compBreaker(self, node):
- from ast import (Compare, BinOp, BitAnd)
- assert isinstance(node, Compare)
- if len(node.comparators) == 1:
- return node
- else:
- comp1 = Compare(node.left, node.ops[0:1],
- node.comparators[0:1])
- comp2 = Compare(node.comparators[0],
- node.ops[1:], node.comparators[1:])
- newNode = BinOp(comp1, BitAnd(), self.compBreaker(comp2))
- return newNode
-
-
-class UnitCalculator(object):
- def __init__(self, localDict):
- self.localDict = localDict
-
- def getUnitAndDim(self, node):
- from ast import (Expression, Name, Num,
- BinOp, Add, Mult, Div, Sub,
- Compare, BoolOp, UnaryOp,
- BitOr, BitXor, BitAnd)
- if isinstance(node, Expression):
- return self.getUnitAndDim(node.body)
- elif isinstance(node, Name):
- if node.id in ['True', 'False']:
- return (1.0, None)
- else:
- column = self.localDict[node.id]
- return (column.unit, column.dimensions)
- elif isinstance(node, Num):
- return (1.0, None)
- elif isinstance(node, BinOp):
- left = self.getUnitAndDim(node.left)
- right = self.getUnitAndDim(node.right)
- dimensions = checkDimensions(left[1], right[1])
- if isinstance(node.op, (Add, Sub)):
- if not isinstance(left[0] / right[0], float):
- raise ValueError("units %s, %s not compatible" \
- % (left, right))
- unit = left[0]
- elif isinstance(node.op, Mult):
- unit = left[0] * right[0]
- elif isinstance(node.op, Div):
- unit = left[0] / right[0]
- elif isinstance(node.op, (BitOr, BitXor, BitAnd)):
- if not isinstance(left[0], float):
- raise ValueError(
- "Type %s cannot be interpreted as a Boolean" % left)
- if not isinstance(right[0], float):
- raise ValueError(
- "Type %s cannot be interpreted as a Boolean" % right)
- unit = 1.0
- else:
- raise NotImplementedError()
- return (unit, dimensions)
- elif isinstance(node, Compare):
- left = self.getUnitAndDim(node.left)
- nonNoneDims = []
- if left[1] is not None:
- nonNoneDims.append(left[1])
- for comparator in node.comparators:
- right = self.getUnitAndDim(comparator)
- if right[1] is not None:
- nonNoneDims.append(right[1])
- if not isinstance(left[0] / right[0], float):
- raise ValueError("units %s, %s not compatible" \
- % (left[0], right[0]))
- if len(nonNoneDims) >= 1:
- for dims in nonNoneDims:
- checkDimensions(nonNoneDims[0], dims)
- dimensions = nonNoneDims[0]
- else:
- dimensions = None
- return (1.0, dimensions)
- elif isinstance(node, BoolOp):
- raise NotImplementedError(
- 'BoolOps not supported. Use bitwise ops instead (&, |)!')
- elif isinstance(node, UnaryOp):
- return self.getUnitAndDim(node.operand)
- else:
- raise NotImplementedError()
-
-
-def checkDimensions(dimensions1, dimensions2):
- if dimensions1 is not None and dimensions2 is not None and \
- dimensions1 != dimensions2:
- msg = 'Dimensions "%s" and "%s" do not match!' \
- % (dimensions1, dimensions2)
- raise ValueError(msg)
- return dimensions1 or dimensions2
Modified: trunk/src/pyphant/pyphant/core/Helpers.py
===================================================================
--- trunk/src/pyphant/pyphant/core/Helpers.py 2011-05-23 12:48:36 UTC (rev 700)
+++ trunk/src/pyphant/pyphant/core/Helpers.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -183,3 +183,27 @@
attributes=attributes, columns=columns)
sc.seal()
return sc
+
+from threading import Lock
+TIMESTAMP_LOCK = Lock()
+LAST_TIMESTAMP = ''
+del Lock
+
+def getModuleUniqueTimestamp():
+ global TIMESTAMP_LOCK
+ global LAST_TIMESTAMP
+ TIMESTAMP_LOCK.acquire()
+ timestamp = None
+ try:
+ from datetime import datetime
+ while True:
+ timestamp = datetime.utcnow()
+ if timestamp != LAST_TIMESTAMP:
+ LAST_TIMESTAMP = timestamp
+ break
+ else:
+ from time import sleep
+ sleep(.001)
+ finally:
+ TIMESTAMP_LOCK.release()
+ return timestamp
Modified: trunk/src/pyphant/pyphant/tests/TestDataContainer.py
===================================================================
--- trunk/src/pyphant/pyphant/tests/TestDataContainer.py 2011-05-23 12:48:36 UTC (rev 700)
+++ trunk/src/pyphant/pyphant/tests/TestDataContainer.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -557,17 +557,20 @@
class AlgebraSampleContainerTests(SampleContainerTest):
def testNodeTransformer(self):
- from pyphant.core.DataContainer import (ReplaceName, ReplaceOperator)
+ from pyphant.core.AstTransformers import (ReplaceName, ReplaceOperator,
+ ReplaceCompare)
rpn = ReplaceName(self.sampleContainer)
import ast
exprStr = 'col("i") / (col("t") + col("t"))'
expr = compile(exprStr, "<TestCase>", 'eval', ast.PyCF_ONLY_AST)
replacedExpr = rpn.visit(expr)
- #print rpn.localDict
- #print ast.dump(replacedExpr)
- rpb = ReplaceOperator(rpn.localDict)
- factorExpr = rpb.visit(replacedExpr)
- #print ast.dump(factorExpr)
+ print rpn.localDict
+ print ast.dump(replacedExpr)
+ rpc = ReplaceCompare(rpn.localDict)
+ factorExpr = rpc.visit(replacedExpr)
+ rpo = ReplaceOperator(rpn.localDict)
+ factorExpr = rpo.visit(factorExpr)
+ print ast.dump(factorExpr)
def testCalcColumn(self):
exprStr = 'col("i") / (col("t") + col("t")) + "1km/s"'
@@ -854,7 +857,7 @@
#purely one dimensional Tests:
def testConsistancy(self):
result1 = self.sampleContainer.filter(
- '("20m" < col("i")) & ("80m" > col("i"))')
+ '"20m" < col("i") and "80m" > col("i")')
result2 = self.sampleContainer.filter('"20m" < col("i") < "80m"')
self.assertEqual(result1[0], result2[0])
self.assertEqual(result1[1], result2[1])
@@ -875,7 +878,7 @@
def testANDExpression(self):
result = self.sampleContainer.filter(
- '(col("i") >= "20m") & (col("t") <= "98.5s")')
+ 'col("i") >= "20m" and col("t") <= "98.5s"')
expectedi = self.sampleContainer["i"][20:98]
expectedt = self.sampleContainer["t"][20:98]
expectedi.attributes = {}
@@ -916,21 +919,32 @@
[True, True, False, True, True])
def testNot2dExpression(self):
- self._compareExpected('~ (col("t") == "10s")',
+ self._compareExpected('not col("t") == "10s"',
[True, True, True, False, True])
def testAnd2dExpression(self):
self._compareExpected(
- '(col("Zeit") == "60s") & ("20000m" == col("Strecke"))',
+ 'col("Zeit") == "60s" and "20000m" == col("Strecke")',
[False, False, True, False, False])
+ def testMultiAnd2dExpression(self):
+ self._compareExpected(
+ "col('l') >= '0 km' and col('l') < '20 km' and col('t') <= '60s'",
+ [False, True, False, True, False])
+
def testOr2dExpression(self):
self._compareExpected(
- '(col("Zeit") < "60s") | (col("Strecke") == "5500m")',
+ 'col("Zeit") < "60s" or col("Strecke") == "5500m"',
[True, True, False, True, True])
+ def testMultiOr2dExpression(self):
+ self._compareExpected(
+ "col('t') == '20s' or col('l') == '0 km' or col('t') > '1000.2 s'",
+ [True, True, False, False, True]
+ )
+
def testMultipleCompareOpPrecedence2dExpression(self):
- self._compareExpected('~ ("0m" <= col("l") <= "10000m")',
+ self._compareExpected('not "0m" <= col("l") <= "10000m"',
[True, False, True, False, False])
def testColumnToColumn2dExpression(self):
Copied: trunk/src/pyphant/pyphant/tests/TestTimestamp.py (from rev 700, trunk/src/workers/OSC/OSC/__init__.py)
===================================================================
--- trunk/src/pyphant/pyphant/tests/TestTimestamp.py (rev 0)
+++ trunk/src/pyphant/pyphant/tests/TestTimestamp.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011, Rectorate of the University of Freiburg
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the Freiburg Materials Research Center,
+# University of Freiburg nor the names of its contributors may be used to
+# endorse or promote products derived from this software without specific
+# prior written permission.
+#
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+u"""Provides test for unique timestamps
+"""
+
+__id__ = "$Id$"
+__author__ = "$Author$"
+__version__ = "$Revision$"
+# $Source$
+
+import unittest
+import pkg_resources
+
+pkg_resources.require("pyphant")
+
+
+class TestModuleUniqueTimestamp(unittest.TestCase):
+ def testUnique(self):
+ from pyphant.core.Helpers import getModuleUniqueTimestamp
+ for x in xrange(100):
+ self.assertNotEqual(
+ getModuleUniqueTimestamp(),
+ getModuleUniqueTimestamp())
+
+
+if __name__ == '__main__':
+ unittest.main()
Modified: trunk/src/pyphant/pyphant/wxgui2/wxPyphantApplication.py
===================================================================
--- trunk/src/pyphant/pyphant/wxgui2/wxPyphantApplication.py 2011-05-23 12:48:36 UTC (rev 700)
+++ trunk/src/pyphant/pyphant/wxgui2/wxPyphantApplication.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -533,10 +533,10 @@
if isinstance(exep, socket_error):
try:
#Python 2.6
- eno = err.errno
+ eno = exep.errno
except AttributeError:
#Python 2.5
- eno = err.args[0]
+ eno = exep.args[0]
from errno import EADDRINUSE
if eno == EADDRINUSE:
msg += "\nReason: Could not find a free port."\
@@ -620,6 +620,7 @@
# The program will freeze without this line.
evt.Skip() # Make sure the default handler runs too...
+ self.Destroy()
import optparse
Modified: trunk/src/workers/ImageProcessing/ImageProcessing/EnhanceContrast.py
===================================================================
--- trunk/src/workers/ImageProcessing/ImageProcessing/EnhanceContrast.py 2011-05-23 12:48:36 UTC (rev 700)
+++ trunk/src/workers/ImageProcessing/ImageProcessing/EnhanceContrast.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -38,8 +38,7 @@
__version__ = "$Revision$"
# $Source$
-from pyphant.core import (Worker, Connectors)
-from ImageProcessing.NDImageWorker import pile
+from pyphant.core import (Worker, Connectors, DataContainer)
import scipy, copy
def normalizeHistogram(data):
@@ -60,12 +59,12 @@
API = 2
VERSION = 1
REVISION = "$Revision$"[11:-1]
- name = "EnhanceContrast"
+ name = "Enhance Contrast"
_sockets = [("image", Connectors.TYPE_IMAGE)]
@Worker.plug(Connectors.TYPE_IMAGE)
def enhance(self, image, subscriber=0):
- newdata = pile(normalizeLinear, image.data)
+ newdata = normalizeLinear(image.data)
longname = "Normalize"
result = DataContainer.FieldContainer(
newdata,
@@ -78,5 +77,4 @@
copy.deepcopy(image.attributes),
False)
result.seal()
- #print newdata.shape
return result
Modified: trunk/src/workers/ImageProcessing/ImageProcessing/FitBackground.py
===================================================================
--- trunk/src/workers/ImageProcessing/ImageProcessing/FitBackground.py 2011-05-23 12:48:36 UTC (rev 700)
+++ trunk/src/workers/ImageProcessing/ImageProcessing/FitBackground.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -47,7 +47,7 @@
API = 2
VERSION = 1
REVISION = "$Revision$"[11:-1]
- name = "FitBackground"
+ name = "Fit Background"
_sockets = [("image", Connectors.TYPE_IMAGE)]
_params = [("poldegree", "Polynomial degree (1 to 5)", 3, None),
("swidth", "sample width", 150, None),
@@ -102,34 +102,22 @@
brightsize = int(self.paramBrightsize.value)
brightruns = int(self.paramBrightruns.value)
dopreview = self.paramDopreview.value
- assert image.data.ndim in [2, 3]
- if image.data.ndim == 2:
- pile = [image.data]
- else:
- pile = image.data
+ data = image.data
#Median:
for run in xrange(medianruns):
- pile = [ndimage.median_filter(data,
- size=mediansize) for data in pile]
+ data = ndimage.median_filter(data, size=mediansize)
#Suspend dark spots:
for run in xrange(darkruns):
- pile = [255 - ndimage.grey_erosion(255 - data,
- size=darksize) for data in pile]
+ data = 255 - ndimage.grey_erosion(255 - data, size=darksize)
#Suspend features:
for run in xrange(brightruns):
- pile = [ndimage.grey_erosion(data,
- size=brightsize) for data in pile]
+ data = ndimage.grey_erosion(data, size=brightsize)
#Fit background:
if not dopreview:
- pile = [self.fit(data, poldegree, swidth, sheight,
- threshold) for data in pile]
- if image.data.ndim == 2:
- newdata = pile[0]
- else:
- newdata = numpy.array(pile)
+ data = self.fit(data, poldegree, swidth, sheight, threshold)
longname = "FitBackground"
result = DataContainer.FieldContainer(
- newdata,
+ data,
copy.deepcopy(image.unit),
copy.deepcopy(image.error),
copy.deepcopy(image.mask),
@@ -139,4 +127,4 @@
copy.deepcopy(image.attributes),
False)
result.seal()
- return result
\ No newline at end of file
+ return result
Modified: trunk/src/workers/ImageProcessing/ImageProcessing/InvertWorker.py
===================================================================
--- trunk/src/workers/ImageProcessing/ImageProcessing/InvertWorker.py 2011-05-23 12:48:36 UTC (rev 700)
+++ trunk/src/workers/ImageProcessing/ImageProcessing/InvertWorker.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -56,7 +56,7 @@
max = scipy.amax(image.data)
min = scipy.amin(image.data)
data = max + min - image.data
- from DataContainer import FieldContainer
+ from pyphant.core.DataContainer import FieldContainer
result = FieldContainer(data, unit=image.unit,
dimensions=copy.deepcopy(image.dimensions),
mask=copy.deepcopy(image.mask),
Added: trunk/src/workers/ImageProcessing/ImageProcessing/LoadZStack.py
===================================================================
--- trunk/src/workers/ImageProcessing/ImageProcessing/LoadZStack.py (rev 0)
+++ trunk/src/workers/ImageProcessing/ImageProcessing/LoadZStack.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -0,0 +1,138 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2006-2011, Rectorate of the University of Freiburg
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the Freiburg Materials Research Center,
+# University of Freiburg nor the names of its contributors may be used to
+# endorse or promote products derived from this software without specific
+# prior written permission.
+#
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+u"""
+The Load ZStack worker is a class of Pyphant's Image Processing
+Toolbox. It simply loads a set of images from the location given in the
+worker's configuration as a 3d image.
+"""
+
+__id__ = "$Id$"
+__author__ = "$Author$"
+__version__ = "$Revision$"
+# $Source$
+
+from pyphant.core.Connectors import (SUBTYPE_FILE, TYPE_IMAGE)
+from pyphant.core import Worker
+
+
+class LoadZStack(Worker.Worker):
+ API = 2
+ VERSION = 1
+ REVISION = "$Revision$"[11:-1]
+ name = "Load ZStack"
+ _params = [
+ ("path", u"Path (select any file)", "", SUBTYPE_FILE),
+ ("regex", u"File Filter Regex", r'(?i)^.+\.tif$', None),
+ ("fieldUnit", u"Unit of the field", 1, None),
+ ("dz", u"z increment", '1 mum', None),
+ ("dy", u"y increment", '1 mum', None),
+ ("dx", u"x increment", '1 mum', None),
+ ("startz", u"z start", '0 mum', None),
+ ("starty", u"y start", '0 mum', None),
+ ("startx", u"x start", '0 mum', None),
+ ("zClip", u"Clipping of z-axis (pixels)", ':', None),
+ ("yClip", u"Clipping of y-axis (pixels)", ':', None),
+ ("xClip", u"Clipping of x-axis (pixels)", ':', None),
+ ("dtype", u"data type", 'uint8', None),
+ ("longname", u"Longname", 'ZStack', None),
+ ("shortname", u"Shortname", 'I', None)
+ ]
+
+ @Worker.plug(TYPE_IMAGE)
+ def loadImageAsGreyScale(self, subscriber=0):
+ import os
+ import re
+ from scipy.misc import imread
+ import numpy
+ from pyphant.core.DataContainer import FieldContainer
+ from pyphant.quantities import Quantity
+ path = os.path.realpath(self.paramPath.value)
+ if os.path.isfile(path):
+ path = os.path.dirname(path)
+ pattern = re.compile(self.paramRegex.value)
+ filenames = filter(
+ lambda x: pattern.match(x) is not None, os.listdir(path)
+ )
+ filenames.sort()
+ filenames = [os.path.join(path, fname) for fname in filenames]
+ print path
+ zClip = self.getClip(self.paramZClip.value)
+ filenames = filenames[zClip[0]:zClip[1]]
+ assert len(filenames) >= 1
+ yClip = self.getClip(self.paramYClip.value)
+ xClip = self.getClip(self.paramXClip.value)
+ dtype = self.paramDtype.value
+ data = []
+ for i, fn in enumerate(filenames):
+ subscriber %= 1 + 99 * i / len(filenames)
+ data.append(imread(fn, True)[yClip[0]:yClip[1], xClip[0]:xClip[1]])
+ data = numpy.array(data, dtype=dtype)
+ axes = ['z', 'y', 'x']
+ dimensions = [
+ self.getDimension(a, data.shape[i]) for i, a in enumerate(axes)
+ ]
+ try:
+ unit = Quantity(self.paramFieldUnit.value)
+ except AttributeError:
+ unit = self.paramFieldUnit.value
+ longname = self.paramLongname.value
+ shortname = self.paramShortname.value
+ image = FieldContainer(
+ data=data, dimensions=dimensions, unit=unit,
+ longname=longname, shortname=shortname,
+ attributes={'yFactor':Quantity(self.paramDy.value),
+ 'xFactor':Quantity(self.paramDx.value)}
+ )
+ image.seal()
+ subscriber %= 100
+ return image
+
+ def getClip(self, clipStr):
+ split = clipStr.split(':')
+ assert len(split) == 2
+ return [int(x) if len(x) else None for x in split]
+
+ def getDimension(self, axis, length):
+ from pyphant.quantities import Quantity
+ from pyphant.core.DataContainer import FieldContainer
+ import numpy
+ delta = Quantity(self.getParam('d' + axis).value)
+ start = Quantity(self.getParam('start' + axis).value)
+
+ start = start.inUnitsOf(delta.unit)
+ data = start.value + numpy.arange(0, length, dtype=float) * delta.value
+ dim = FieldContainer(
+ data, unit=Quantity(1.0, delta.unit),
+ shortname=axis,
+ longname='%s-Axis' % (axis.upper(), )
+ )
+ return dim
Modified: trunk/src/workers/ImageProcessing/ImageProcessing/Medianiser.py
===================================================================
--- trunk/src/workers/ImageProcessing/ImageProcessing/Medianiser.py 2011-05-23 12:48:36 UTC (rev 700)
+++ trunk/src/workers/ImageProcessing/ImageProcessing/Medianiser.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -50,7 +50,7 @@
API = 2
VERSION = 1
REVISION = "$Revision$"[11:-1]
- name = "Medianiser"
+ name = "Median"
_sockets = [("field", Connectors.TYPE_IMAGE)]
_params = [("size", "Kernel Size", 5, None),
("runs", "Runs", 3, None)]
@@ -63,4 +63,4 @@
for i in range(ru):
im.data = scipy.ndimage.filters.median_filter(im.data, size=size)
im.seal()
- return im
\ No newline at end of file
+ return im
Deleted: trunk/src/workers/ImageProcessing/ImageProcessing/NDImageWorker.py
===================================================================
--- trunk/src/workers/ImageProcessing/ImageProcessing/NDImageWorker.py 2011-05-23 12:48:36 UTC (rev 700)
+++ trunk/src/workers/ImageProcessing/ImageProcessing/NDImageWorker.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -1,183 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2006-2007, Rectorate of the University of Freiburg
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-# * Neither the name of the Freiburg Materials Research Center,
-# University of Freiburg nor the names of its contributors may be used to
-# endorse or promote products derived from this software without specific
-# prior written permission.
-#
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-u"""
-TODO: Check units, repair functionality
-"""
-
-__id__ = "$Id$"
-__author__ = "$Author$"
-__version__ = "$Revision$"
-# $Source$
-
-from pyphant.core import Worker, Connectors,\
- Param, DataContainer
-import ImageProcessing
-import numpy, copy
-from scipy import ndimage
-
-def pile(func, imagedata, runs=1, dopile=True):
- assert imagedata.ndim in [2, 3]
- assert runs >= 0
- if runs == 0:
- return imagedata
- if imagedata.ndim == 2 or not dopile:
- pile = [imagedata]
- else:
- pile = imagedata
- for run in xrange(runs):
- pile = [func(data) for data in pile]
- if imagedata.ndim == 2 or not dopile:
- newdata = pile[0]
- else:
- newdata = numpy.array(pile)
- return newdata
-
-
-class NDImage(Worker.Worker):
- API = 2
- VERSION = 1
- REVISION = "$Revision$"[11:-1]
- name = "ndimage"
- _sockets = [("image", Connectors.TYPE_IMAGE)]
- _filters = {"binary_closing":("iterations", ),
- "binary_opening":("iterations", ),
- "binary_fill_holes":(),
- "binary_erosion":("iterations", ),
- "binary_dilation":("iterations", ),
- "maximum_filter":("size", "mode", "cval"),
- "median_filter":("size", "mode", "cval"),
- "grey_closing":("size", "mode", "cval"),
- "grey_erosion":("size", "mode", "cval"),
- "grey_opening":("size", "mode", "cval"),
- "distance_transform_bf":("metric", ),
- "sobel":("axis", "mode", "cval"),
- "grey_invert":(None, ),
- "cut_histogram":(None, "tolerance"),
- "label":(None, "connectivity"),
- "threshold":(None, "threshold"),
- "area_opening":(None, "size")}
- _ndparams = {"iterations":1,
- "size":5,
- "mode":["reflect",
- "nearest",
- "wrap",
- "constant"],
- "cval":0,
- "tolerance":1000,
- "connectivity":2,
- "metric":["euclidean",
- "taxicab",
- "chessboard"],
- "threshold":"1 m",
- "axis":-1}
- _params = [("pile", "Treat 3d images as pile of 2d images", True, None),
- ("ndfilter", "Filter", _filters.keys(), None)]
- _params += [(pn, pn, dflt, None) for pn, dflt in _ndparams.iteritems()]
-
- def area_opening(self, data, size):
- structure = ndimage.morphology.generate_binary_structure(data.ndim,
- 2)
- labels = ndimage.label(data, structure=structure)[0]
- slices = ndimage.find_objects(labels)
- areas = [numpy.where(labels[sli] == label + 1, True, False).sum() \
- for label, sli in enumerate(slices)]
- print areas
- output = numpy.zeros(data.shape, dtype=data.dtype)
- for label, sli, area in zip(range(len(slices)), slices, areas):
- if area >= size:
- output[sli] |= numpy.where(labels[sli] == label + 1, data[sli], 0)
- return output
-
- def threshold(self, data, threshold):
- from pyphant.quantities import (Quantity,
- isQuantity)
- from pyphant.core.Helpers import uc2utf8
- try:
- thp = Quantity(uc2utf8(threshold))
- except:
- thp = float(threshold)
- thp /= self._unit
- assert not isQuantity(thp)
- return numpy.where(data < thp, False, True)
-
- def grey_invert(self, data):
- return 255 - data
-
- def label(self, data, connectivity):
- structure = ndimage.morphology.generate_binary_structure(data.ndim,
- connectivity)
- return ndimage.label(data, structure=structure)[0]
-
- def cut_histogram(self, data, tolerance):
- hist = ndimage.histogram(data, 0, 256, 256)
- csum = numpy.cumsum(hist)
- cut = csum[255] / tolerance
- for i in xrange(len(csum)):
- if csum[i] > cut:
- newmin = i
- break
- meanvalue = data.mean()
- return numpy.where(data < newmin, meanvalue, data)
-
- def applyfilter(self, data):
- if None in self._filters[self.paramNdfilter.value]:
- call = getattr(self, self.paramNdfilter.value)
- else:
- call = getattr(ndimage, self.paramNdfilter.value)
- args = {}
- for par in self._filters[self.paramNdfilter.value]:
- if par != None:
- args[par] = self.getParam(par).value
- #print args
- return call(data, **args)
-
- @Worker.plug(Connectors.TYPE_IMAGE)
- def ndimage(self, image, subscriber=0):
- self._unit = image.unit
- if "iterations" in self._filters[self.paramNdfilter.value]:
- runs = 1
- else:
- runs = self.paramIterations.value
- newdata = pile(self.applyfilter, image.data, runs, self.paramPile.value)
- longname = "%s" % (self.paramNdfilter.value, )
- result = DataContainer.FieldContainer(
- newdata,
- copy.deepcopy(image.unit),
- None,
- copy.deepcopy(image.mask),
- copy.deepcopy(image.dimensions),
- longname,
- image.shortname,
- copy.deepcopy(image.attributes),
- False)
- result.seal()
- return result
Modified: trunk/src/workers/ImageProcessing/ImageProcessing/ThresholdingWorker.py
===================================================================
--- trunk/src/workers/ImageProcessing/ImageProcessing/ThresholdingWorker.py 2011-05-23 12:48:36 UTC (rev 700)
+++ trunk/src/workers/ImageProcessing/ImageProcessing/ThresholdingWorker.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -53,14 +53,28 @@
REVISION = "$Revision$"[11:-1]
name = "Threshold"
_sockets = [("image", Connectors.TYPE_IMAGE)]
- _params = [("threshold", "Threshold", 160, None),
+ _params = [("threshold", "Threshold", "160.0", None),
+ ("unit", "Unit", "ignore", None)
# ("mode", "Mode(absolute/coverage)",
# ["absolute", "coverage"], None)
]
@Worker.plug(Connectors.TYPE_IMAGE)
def threshold(self, image, subscriber=0):
- th = self.paramThreshold.value
+ th = float(self.paramThreshold.value)
+ if self.paramUnit.value.lower() != 'ignore':
+ from pyphant.quantities import Quantity, isQuantity
+ try:
+ unit = float(self.paramUnit.value)
+ assert not isQuantity(image.unit)
+ except ValueError:
+ try:
+ unit = Quantity(self.paramUnit.value)
+ except TypeError:
+ unit = Quantity(1.0, self.paramUnit.value)
+ assert isQuantity(image.unit)
+ assert unit.isCompatible(image.unit.unit)
+ th *= unit / image.unit
resultArray = scipy.where(image.data < th,
ImageProcessing.FEATURE_COLOR,
ImageProcessing.BACKGROUND_COLOR)
@@ -68,4 +82,4 @@
dimensions=copy.deepcopy(image.dimensions),
longname=u"Binary Image", shortname=u"B")
result.seal()
- return result
\ No newline at end of file
+ return result
Modified: trunk/src/workers/ImageProcessing/ImageProcessing/Watershed.py
===================================================================
--- trunk/src/workers/ImageProcessing/ImageProcessing/Watershed.py 2011-05-23 12:48:36 UTC (rev 700)
+++ trunk/src/workers/ImageProcessing/ImageProcessing/Watershed.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -39,7 +39,6 @@
# $Source$
from pyphant.core import (Worker, Connectors, DataContainer)
-from ImageProcessing.NDImageWorker import pile
import copy
import heapq
import scipy
@@ -96,7 +95,7 @@
@Worker.plug(Connectors.TYPE_IMAGE)
def wsworker(self, image, markers, subscriber=0):
self._markers = markers.data
- newdata = pile(self.watershed, image.data)
+ newdata = self.watershed(image.data)
longname = "Watershed"
result = DataContainer.FieldContainer(newdata,
copy.deepcopy(image.unit),
Modified: trunk/src/workers/ImageProcessing/ImageProcessing/__init__.py
===================================================================
--- trunk/src/workers/ImageProcessing/ImageProcessing/__init__.py 2011-05-23 12:48:36 UTC (rev 700)
+++ trunk/src/workers/ImageProcessing/ImageProcessing/__init__.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -56,9 +56,9 @@
"Gradient",
"ImageLoaderWorker",
"InvertWorker",
+ "LoadZStack",
"MarkInclusions",
"Medianiser",
- "NDImageWorker",
"SkeletonizeFeature",
"ThresholdingWorker",
"UltimatePointsCalculator",
Modified: trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestAutoFocus.py
===================================================================
--- trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestAutoFocus.py 2011-05-23 12:48:36 UTC (rev 700)
+++ trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestAutoFocus.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -31,7 +31,8 @@
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-u"""Provides unittest classes for AutoFocus worker.
+u"""Provides unittest classes for AutoFocus, LoadZStack
+and MarkInclusions worker.
"""
__id__ = "$Id$".replace('$','')
@@ -46,32 +47,8 @@
from ImageProcessing import __path__ as ppath
importDir = os.path.join(ppath[0], "tests", "resources",
"zstack")
-from pyphant.quantities import Quantity
-import numpy
-import scipy
-def importZStack(filenames, zUnit, zValues):
- from pyphant.core.DataContainer import FieldContainer
- zDim = FieldContainer(data=zValues, unit=zUnit,
- shortname='z', longname='Z Axis')
- yDim = FieldContainer(data=numpy.arange(.0, 400.0, 1.0) * 1.29,
- unit=Quantity('1.0 mum'),
- shortname='y', longname='Y Axis')
- xDim = FieldContainer(data=numpy.arange(.0, 400.0, 1.0) * 1.29,
- unit=Quantity('1.0 mum'),
- shortname='x', longname='X Axis')
- imgData = numpy.zeros((zDim.data.shape[0], yDim.data.shape[0],
- xDim.data.shape[0]), dtype='uint8')
- for i, filename in enumerate(filenames):
- imgData[i] = scipy.misc.imread(os.path.join(importDir, filename),
- flatten=True)
- zStack = FieldContainer(data=imgData, dimensions=[zDim, yDim, xDim],
- shortname='I', longname='ZStack')
- zStack.seal()
- return zStack
-
-
class ZStackTestCase(unittest.TestCase):
def setUp(self):
pass
@@ -87,12 +64,13 @@
def testZStack(self):
print "Importing ZStack..."
- zstack = importZStack(
- filenames=filter(lambda x: x.endswith('.tif'),
- sorted(os.listdir(importDir))),
- zUnit=Quantity('1.0 mum'),
- zValues = numpy.arange(0.0, 601.0, 100.0)
- )
+ from ImageProcessing.LoadZStack import LoadZStack
+ loader = LoadZStack()
+ loader.paramPath.value = importDir
+ loader.paramDz.value = '100.0 mum'
+ loader.paramDy.value = '1.29 mum'
+ loader.paramDx.value = '1.29 mum'
+ zstack = loader.loadImageAsGreyScale()
print "Done."
print "Calculating ZStack-statistics..."
from ImageProcessing.AutoFocus import AutoFocus
@@ -114,11 +92,15 @@
def testSingle(self):
print "Importing single image..."
- zstack = importZStack(
- filenames=['TestZStack_z03.tif'],
- zUnit=Quantity('1.0 mum'),
- zValues = numpy.array([300.0, ])
- )
+ from ImageProcessing.LoadZStack import LoadZStack
+ loader = LoadZStack()
+ loader.paramPath.value = os.path.join(importDir, 'TestZStack_z00.tif')
+ loader.paramDz.value = '100.0 mum'
+ loader.paramDy.value = '1.29 mum'
+ loader.paramDx.value = '1.29 mum'
+ loader.paramStartz.value = '300.0 mum'
+ loader.paramZClip.value = '3:4'
+ zstack = loader.loadImageAsGreyScale()
print "Done."
print "Calculating single image statistics..."
from ImageProcessing.AutoFocus import AutoFocus
@@ -138,7 +120,24 @@
self.check((300.0, 0.0), statistics['zPos'].data[imin])
self.check((7.0 * mul, mul), statistics['diameter'].data[imin])
+ def testMarkInclusions(self):
+ from ImageProcessing.LoadZStack import LoadZStack
+ from ImageProcessing.MarkInclusions import MarkInclusions
+ loader = LoadZStack()
+ loader.paramPath.value = importDir
+ loader.paramDz.value = '100.0 mum'
+ loader.paramDy.value = '1.29 mum'
+ loader.paramDx.value = '1.29 mum'
+ zstack = loader.loadImageAsGreyScale()
+ from ImageProcessing.AutoFocus import AutoFocus
+ afw = AutoFocus()
+ statistics = afw.getStatistics(zstack)
+ minc = MarkInclusions()
+ marked = minc.markInclusions(zstack, statistics)
+ self.assertEqual(zstack.dimensions, marked.dimensions)
+ self.assertEqual(zstack.unit, marked.unit)
+
if __name__ == "__main__":
import sys
if len(sys.argv) == 1:
Added: trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestCoverage.py
===================================================================
--- trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestCoverage.py (rev 0)
+++ trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestCoverage.py 2011-11-17 10:26:46 UTC (rev 701)
@@ -0,0 +1,88 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2006-2007, Rectorate of the University of Freiburg
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must...
[truncated message content] |