| 
     
      
      
      From: <zk...@us...> - 2010-07-12 20:43:18
      
     
   | 
Revision: 695
          http://pyphant.svn.sourceforge.net/pyphant/?rev=695&view=rev
Author:   zklaus
Date:     2010-07-12 20:43:11 +0000 (Mon, 12 Jul 2010)
Log Message:
-----------
Merge branch 'master' into svn-trunk
* master:
  Enh: Import of single microscopy images
Modified Paths:
--------------
    trunk/src/pyphant/pyphant/core/ZStackManager.py
    trunk/src/pyphant/pyphant/tests/TestZStacks.py
    trunk/src/pyphant/pyphant/tests/resources/zstack/_meta.xml
    trunk/src/pyphant/pyphant/wxgui2/wxPyphantApplication.py
    trunk/src/workers/ImageProcessing/ImageProcessing/MarkAF.py
Added Paths:
-----------
    trunk/src/pyphant/pyphant/tests/resources/zstack/single_meta.xml
Modified: trunk/src/pyphant/pyphant/core/ZStackManager.py
===================================================================
--- trunk/src/pyphant/pyphant/core/ZStackManager.py	2010-07-08 13:13:29 UTC (rev 694)
+++ trunk/src/pyphant/pyphant/core/ZStackManager.py	2010-07-12 20:43:11 UTC (rev 695)
@@ -39,65 +39,27 @@
 # $Source$
 
 
-from pyphant.core.XMLHandler import getXMLRoot
 from pyphant.quantities import Quantity
 from pyphant.core.DataContainer import (FieldContainer, SampleContainer)
 import scipy
 import Image
 from pyphant.core.KnowledgeManager import KnowledgeManager
 import os
+import re
 kmanager = KnowledgeManager.getInstance()
 
 
 class ZStack(object):
-    def __init__(self, sc_id=None, name=None, xml_file=None, temporary=False):
-        """Initializes a ZStack from an existing id or a local source"""
-        assert (sc_id is None) is not (xml_file is None)
+    def __init__(self, sc_id=None, meta=None, temporary=False):
+        """Initializes a ZStack from an existing id or metadata"""
+        assert (sc_id is None) is not (meta is None)
         self.temporary = temporary
-        self._recipe_path = None
         if sc_id is not None:
             self.repr_sc = kmanager.getDataContainer(sc_id)
         else:
-            assert name is not None
-            self.repr_sc = self._import_zstack(name,
-                                               os.path.realpath(xml_file))
+            self.repr_sc = self._import_zstack(meta)
 
     @staticmethod
-    def _get_images_meta(xml_file):
-        def getFloat(xmlelement):
-            return float(xmlelement.content.strip().replace(',', '.'))
-
-        def getMum(xmlelement):
-            return Quantity(getFloat(xmlelement), 'mum')
-
-        base_path = os.path.dirname(xml_file)
-        xml_root = getXMLRoot(xml_file)
-        images_meta = []
-        for ztag in [value for key, value in xml_root.children.iteritems()\
-                     if key.startswith('z')]:
-            meta = {}
-            fname = xml_root['Tags']['V5'].content.strip()
-            root, ext = os.path.splitext(fname)
-            fname = "%s_%s%s" % (root, ztag.name, ext)
-            meta['img_filename'] = os.path.join(base_path, fname)
-            meta['zvi_filename'] = os.path.join(
-                base_path, xml_root['Tags']['V150'].content.strip())
-            meta['xml_filename'] = xml_file
-            meta['zid'] = ztag.name
-            ztag = ztag['Tags']
-            meta['timestamp'] = ztag['V44'].content.strip()
-            meta['width'] = int(ztag['V3'].content.strip())
-            meta['height'] = int(ztag['V4'].content.strip())
-            meta['x-pos'] = getMum(ztag['V15'])
-            meta['y-pos'] = getMum(ztag['V16'])
-            meta['z-pos'] = getMum(ztag['V93'])
-            meta['pixel_width'] = getMum(xml_root['Scaling']['Factor_0'])
-            meta['pixel_height'] = getMum(xml_root['Scaling']['Factor_1'])
-            images_meta.append(meta)
-        images_meta.sort(key = lambda x: x['z-pos'].value)
-        return images_meta
-
-    @staticmethod
     def _get_image_fcs(images_meta, temporary=False):
         zvalues = []
         emd5s = []
@@ -111,47 +73,43 @@
         count = 1
         for img_meta in images_meta:
             if pdial is not None:
-                pdial.Update(count, os.path.basename(img_meta['img_filename']))
+                pdial.Update(count, os.path.basename(img_meta['imgFilename']))
                 count += 1
-            files.append(img_meta['xml_filename'])
-            img = Image.open(img_meta['img_filename'])
+            files.append(img_meta['xmlFilename'])
+            img = Image.open(img_meta['imgFilename'])
             data = scipy.misc.fromimage(img, flatten=True)
             zvalue = img_meta['z-pos']
-            ydata = scipy.arange(img_meta['height']) \
-                    * img_meta['pixel_height'].inUnitsOf('mum').value \
-                    + img_meta['y-pos'].inUnitsOf('mum').value
-            xdata = scipy.arange(img_meta['width']) \
-                    * img_meta['pixel_width'].inUnitsOf('mum').value \
-                    + img_meta['x-pos'].inUnitsOf('mum').value
+            yunit = Quantity(1.0, img_meta['height'].unit)
+            xunit = Quantity(1.0, img_meta['width'].unit)
+            ydata = scipy.arange(img_meta['height[pixel]']) \
+                    * img_meta['y-factor'].inUnitsOf(yunit.unit).value \
+                    + img_meta['y-pos'].inUnitsOf(yunit.unit).value
+            xdata = scipy.arange(img_meta['width[pixel]']) \
+                    * img_meta['x-factor'].inUnitsOf(xunit.unit).value \
+                    + img_meta['x-pos'].inUnitsOf(xunit.unit).value
             dimensions = [FieldContainer(ydata,
-                                         unit=Quantity(1.0, 'mum'),
+                                         unit=yunit,
                                          longname=u'y-axis',
                                          shortname=u'y'),
                           FieldContainer(xdata,
-                                         unit=Quantity(1.0, 'mum'),
+                                         unit=xunit,
                                          longname=u'x-axis',
                                          shortname=u'x')]
-            fcattr = {'img_filename':img_meta['img_filename'],
-                      'xml_filename':img_meta['xml_filename'],
-                      'zvi_filename':img_meta['zvi_filename'],
-                      'zvalue':zvalue,
-                      'timestamp':img_meta['timestamp'],
-                      'zid':img_meta['zid'],
-                      'ZStackType':'RawImage',
-                      'vmin':0, 'vmax':255}
+            fcattr = {'vmin':0, 'vmax':255}
+            fcattr.update(img_meta)
             img_fc = FieldContainer(data=data,
                                     longname=os.path.basename(
-                                        img_meta['img_filename']),
+                                        img_meta['imgFilename']),
                                     shortname="i",
                                     dimensions=dimensions, attributes=fcattr)
             img_fc.seal()
             kmanager.registerDataContainer(img_fc, temporary=temporary)
             emd5s.append(img_fc.id)
-            zvalues.append(zvalue.inUnitsOf('mum').value)
+            zvalues.append(zvalue.value)
         if len(zvalues) == 0:
             return None, None, None
         zfc = FieldContainer(scipy.array(zvalues), longname='z-value',
-                             shortname='z', unit=Quantity(1.0, 'mum'))
+                             shortname='z', unit=Quantity(1.0, zvalue.unit))
         filefc = FieldContainer(scipy.array(files), longname='filename',
                                 shortname='f')
         emd5fc = FieldContainer(scipy.array(emd5s), longname='emd5',
@@ -160,26 +118,16 @@
             pdial.Destroy()
         return zfc, filefc, emd5fc
 
-    @staticmethod
-    def _estimate_ztol(zfc):
-        zmums = [(float(zvalue) * zfc.unit).inUnitsOf('mum').value \
-                 for zvalue in zfc.data]
-        zmums.sort()
-        diffs = []
-        for index in xrange(len(zmums) - 1):
-            diffs.append(zmums[index + 1] - zmums[index])
-        return Quantity(2.0 * sum(diffs) / float(len(diffs)), 'mum')
-
-    def _import_zstack(self, name, xml_file):
-        images_meta = ZStack._get_images_meta(xml_file)
-        zfc, filefc, emd5fc = ZStack._get_image_fcs(images_meta, self.temporary)
+    def _import_zstack(self, meta):
+        zfc, filefc, emd5fc = ZStack._get_image_fcs(meta, self.temporary)
         if zfc == None:
             return None
         attributes = {}
-        attributes['ztol'] = ZStack._estimate_ztol(zfc)
         attributes['ZStackType'] = 'RawSC'
+        attributes['xmlFilename'] = meta[0]['xmlFilename']
+        attributes['crystal'] = meta[0]['crystal']
         ssc = SampleContainer([zfc, filefc, emd5fc],
-                              name,
+                              meta[0]['ZStackName'],
                               "z",
                               attributes)
         ssc.seal()
@@ -188,9 +136,10 @@
 
 
 class ZStackManager(object):
-    def addZStack(self, zstack):
-        """Adds a given zstack to the pool"""
-        kmanager.registerDataContainer(zstack.repr_sc)
+    def importZStack(self, xmlFName, name, crystal, temporary=False):
+        metaReader = getMetaReader(xmlFName, name, crystal)
+        meta = metaReader.getMeta()
+        return ZStack(meta=meta, temporary=temporary)
 
     def getZStacks(self):
         """Returns a list of all ZStacks in the pool"""
@@ -208,3 +157,141 @@
             raise ValueError("There is no ZStack called %s!" \
                                  % name)
         return ZStack(sc_id=sresult[0][0])
+
+
+class MetaReader(object):
+    def __init__(self, xmlFName, name, crystal):
+        self.xmlFName = xmlFName
+        from pyphant.core.XMLHandler import getXMLRoot
+        self.xmlRoot = getXMLRoot(xmlFName)
+        self.zStackName = name
+        self.crystal = crystal
+
+    def getMeta(self):
+        getStr = lambda x: x.content.strip()
+        def getTag(tag, tagstr):
+            for subtag in tagstr.split(':'):
+                tag = tag[subtag]
+            return tag
+        common_meta = {}
+        for key, tagstr in self.commonTagDict.iteritems():
+            common_meta[key] = getStr(getTag(self.xmlRoot, tagstr))
+        common_meta['xmlFilename'] = self.xmlFName
+        images_meta = []
+        for ztag in [value for key, value in self.xmlRoot.children.iteritems()\
+                     if self.tagRe.match(key) is not None]:
+            meta = common_meta.copy()
+            for key, tagstr in self.imageTagDict.iteritems():
+                meta[key] = getStr(getTag(ztag, tagstr))
+            meta['zid'] = self.getZId(ztag.name)
+            meta['pid'] = self.getPId(ztag.name)
+            meta['imgFilename'] = self.getImgFName(ztag.name)
+            meta['ZStackName'] = self.zStackName
+            meta['crystal'] = self.crystal
+            images_meta.append(meta)
+        self.validateMeta(images_meta)
+        images_meta.sort(key = lambda x: x['z-pos'].value)
+        return images_meta
+
+
+class ZStackMetaReader(MetaReader):
+    commonTagDict = {'scalingfactor 0':'Scaling:Factor_0',
+                     'scalingfactor 1':'Scaling:Factor_1',
+                     'SF type 0':'Scaling:Type_0',
+                     'SF type 1':'Scaling:Type_1',
+                     'width[pixel]':'Tags:V25',
+                     'height[pixel]':'Tags:V26',
+                     'width':'Tags:V30',
+                     'height':'Tags:V33',
+                     'width type':'Tags:V28',
+                     'height type':'Tags:V31',
+                     'x-factor':'Tags:V29',
+                     'y-factor':'Tags:V32',
+                     'x-pos':'Tags:V48',
+                     'y-pos':'Tags:V49',
+                     'objective':'Tags:V101'}
+    imageTagDict = {'timestamp':'Tags:V44',
+                    'z-pos':'Tags:V93'}
+    tagRe = re.compile(r'^z[0-9]+$')
+
+    def getImgFName(self, ztagname):
+        fname = self.xmlRoot['Tags']['V5'].content.strip()
+        root, ext = os.path.splitext(fname)
+        fname = "%s_%s%s" % (root, ztagname, ext)
+        return os.path.join(os.path.dirname(self.xmlFName), fname)
+
+    def getZId(self, ztagname):
+        return int(ztagname[1:])
+
+    def getPId(self, ztagname):
+        return 0
+
+    def validateMeta(self, meta):
+        getFloat = lambda x: float(x.replace(',', '.'))
+        getMum = lambda x: Quantity(getFloat(x), 'mum')
+        mumErr = 'Expected micrometre but got different unit!'
+        for img_meta in meta:
+            assert img_meta.pop('SF type 0') == '76', mumErr
+            assert img_meta.pop('SF type 1') == '76', mumErr
+            assert img_meta.pop('width type') == '76', mumErr
+            assert img_meta.pop('height type') == '76', mumErr
+            assert getFloat(img_meta.pop('scalingfactor 0')) \
+                   == getFloat(img_meta['x-factor'])
+            assert getFloat(img_meta.pop('scalingfactor 1')) \
+                   == getFloat(img_meta['y-factor'])
+            for key in ['width', 'height', 'x-factor', 'y-factor', 'x-pos',
+                        'y-pos', 'z-pos']:
+                img_meta[key] = getMum(img_meta[key])
+            for key in ['width[pixel]', 'height[pixel]']:
+                img_meta[key] = int(img_meta[key])
+            assert img_meta['width[pixel]'] == int(round(img_meta['width'] /\
+                   img_meta['x-factor'])), "x scaling is void"
+            assert img_meta['height[pixel]'] == int(round(img_meta['height'] /\
+                   img_meta['y-factor'])), "y scaling is void"
+
+
+class SingleMetaReader(ZStackMetaReader):
+    commonTagDict = {'scalingfactor 0':'Scaling:Factor_0',
+                     'scalingfactor 1':'Scaling:Factor_1',
+                     'SF type 0':'Scaling:Type_0',
+                     'SF type 1':'Scaling:Type_1',
+                     'width[pixel]':'Tags:V11',
+                     'height[pixel]':'Tags:V12',
+                     'width':'Tags:V16',
+                     'height':'Tags:V19',
+                     'width type':'Tags:V14',
+                     'height type':'Tags:V17',
+                     'x-factor':'Tags:V15',
+                     'y-factor':'Tags:V18',
+                     'x-pos':'Tags:V41',
+                     'y-pos':'Tags:V42',
+                     'objective':'Tags:V93',
+                     'timestamp':'Tags:V50',
+                     'z-pos':'Tags:V99'}
+    imageTagDict = {}
+    tagRe = re.compile(r'^_single$')
+
+    def getZId(self, ztagname):
+        return 0
+
+    def getImgFName(self, ztagname):
+        fname = self.xmlRoot['Tags']['V5'].content.strip()
+        return os.path.join(os.path.dirname(self.xmlFName), fname)
+
+META_READERS = [ZStackMetaReader, SingleMetaReader]
+
+def getMetaReader(xml, name, crystal):
+    from pyphant.core.XMLHandler import getXMLRoot
+    root = getXMLRoot(xml)
+    matched = False
+    for key in root.children.iterkeys():
+        for mreader in META_READERS:
+            if mreader.tagRe.match(key) is not None:
+                matched = True
+                break
+        if matched:
+            break
+    if matched:
+        return mreader(xml, name, crystal)
+    else:
+        raise ValueError("Unknown file format in file: %s" % xml)
Modified: trunk/src/pyphant/pyphant/tests/TestZStacks.py
===================================================================
--- trunk/src/pyphant/pyphant/tests/TestZStacks.py	2010-07-08 13:13:29 UTC (rev 694)
+++ trunk/src/pyphant/pyphant/tests/TestZStacks.py	2010-07-12 20:43:11 UTC (rev 695)
@@ -60,12 +60,12 @@
         import os
         from pyphant.core import KnowledgeManager
         from pyphant import __path__ as ppath
-        from pyphant.core.ZStackManager import ZStack
+        from pyphant.core.ZStackManager import ZStackManager
         print "Importing ZStack..."
-        zstack = ZStack(name="TestCase_ZStack",
-                        xml_file=os.path.join(ppath[0], "tests", "resources",
+        zstack = ZStackManager().importZStack(name="TestCase_ZStack",
+                        xmlFName=os.path.join(ppath[0], "tests", "resources",
                                               "zstack", "_meta.xml"),
-                        temporary=True)
+                        temporary=True, crystal='TestCrystal')
         print "Done."
         print "Calculating ZStack-statistics..."
         from ImageProcessing.AutoFocus import AutoFocus
@@ -84,7 +84,25 @@
         self.check((300.0, 0.0), statistics['z-pos'].data[imin])
         self.check((7.0, 1.0), statistics['diameter'].data[imin])
 
+    def testSingle(self):
+        import os
+        from pyphant.core import KnowledgeManager
+        from pyphant import __path__ as ppath
+        from pyphant.core.ZStackManager import ZStackManager
+        print "Importing single image..."
+        zstack = ZStackManager().importZStack(name="TestCase_Single",
+                        xmlFName=os.path.join(ppath[0], "tests", "resources",
+                                              "zstack", "single_meta.xml"),
+                        temporary=True, crystal='TestCrystal2')
+        print "Done."
+        print "Calculating single image statistics..."
+        from ImageProcessing.AutoFocus import AutoFocus
+        afw = AutoFocus()
+        statistics = afw.get_statistics_sc(zstack.repr_sc)
+        print "Done."
+        assert len(statistics['diameter'].data) == 2
 
+
 if __name__ == "__main__":
     import sys
     if len(sys.argv) == 1:
Modified: trunk/src/pyphant/pyphant/tests/resources/zstack/_meta.xml
===================================================================
--- trunk/src/pyphant/pyphant/tests/resources/zstack/_meta.xml	2010-07-08 13:13:29 UTC (rev 694)
+++ trunk/src/pyphant/pyphant/tests/resources/zstack/_meta.xml	2010-07-12 20:43:11 UTC (rev 695)
@@ -2,11 +2,23 @@
 <ROOT>
    <Tags>
      <V5>TestZStack.tif</V5>
-     <V150></V150>
+     <V25>400</V25>
+     <V26>400</V26>
+     <V29>1,0</V29>
+     <V30>400,0</V30>
+     <V28>76</V28>
+     <V32>1,0</V32>
+     <V33>400,0</V33>
+     <V31>76</V31>
+     <V48>0,0</V48>
+     <V49>0,0</V49>
+     <V101>TestObjective</V101>
    </Tags>
    <Scaling>
      <Factor_0>1,00</Factor_0>
      <Factor_1>1,00</Factor_1>
+     <Type_0>76</Type_0>
+     <Type_1>76</Type_1>
    </Scaling>
    <z00>
      <Tags>
Added: trunk/src/pyphant/pyphant/tests/resources/zstack/single_meta.xml
===================================================================
--- trunk/src/pyphant/pyphant/tests/resources/zstack/single_meta.xml	                        (rev 0)
+++ trunk/src/pyphant/pyphant/tests/resources/zstack/single_meta.xml	2010-07-12 20:43:11 UTC (rev 695)
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ROOT>
+   <Tags>
+     <V5>TestZStack_z04.tif</V5>
+     <V11>400</V11>
+     <V12>400</V12>
+     <V15>1,0</V15>
+     <V16>400,0</V16>
+     <V14>76</V14>
+     <V18>1,0</V18>
+     <V19>400,0</V19>
+     <V17>76</V17>
+     <V41>0,0</V41>
+     <V42>0,0</V42>
+     <V93>TestObjective</V93>
+     <V50>12.07.2010 09:40:00</V50>
+     <V99>0,0</V99>
+   </Tags>
+   <Scaling>
+     <Factor_0>1,00</Factor_0>
+     <Factor_1>1,00</Factor_1>
+     <Type_0>76</Type_0>
+     <Type_1>76</Type_1>
+   </Scaling>
+   <_single>
+     <Tags>
+     </Tags>
+   </_single>
+</ROOT>
Modified: trunk/src/pyphant/pyphant/wxgui2/wxPyphantApplication.py
===================================================================
--- trunk/src/pyphant/pyphant/wxgui2/wxPyphantApplication.py	2010-07-08 13:13:29 UTC (rev 694)
+++ trunk/src/pyphant/pyphant/wxgui2/wxPyphantApplication.py	2010-07-12 20:43:11 UTC (rev 695)
@@ -480,7 +480,7 @@
                             defaultFile="", wildcard=wc, style=wx.OPEN)
         if dlg.ShowModal() == wx.ID_OK:
             filename = os.path.realpath(dlg.GetPath())
-            from pyphant.core.ZStackManager import (ZStack, ZStackManager)
+            from pyphant.core.ZStackManager import ZStackManager
             tedlg = wx.TextEntryDialog(self, "Enter name for ZStack:",
                                        "", "ZStack")
             if tedlg.ShowModal() == wx.ID_OK:
@@ -491,10 +491,15 @@
                     cpt2 = "Error"
                     msg2 = "ZStack %s already exists!" % name
                 except ValueError:
-                    zstack = ZStack(name=name, xml_file=filename)
-                    zsm.addZStack(zstack)
-                    cpt2 = "Info"
-                    msg2 = "Successfully imported ZStack."
+                    tedlg2 = wx.TextEntryDialog(self, "Enter crystal name:",
+                                                "", "Crystal01")
+                    if tedlg2.ShowModal() == wx.ID_OK:
+                        crystal = tedlg2.GetValue()
+                        zsm.importZStack(name=name, xmlFName=filename,
+                                         crystal=crystal)
+                        cpt2 = "Info"
+                        msg2 = "Successfully imported ZStack."
+                    tedlg2.Destroy()
                 dlg2 = wx.MessageDialog(self, msg2, cpt2, wx.OK)
                 dlg2.ShowModal()
                 dlg2.Destroy()
Modified: trunk/src/workers/ImageProcessing/ImageProcessing/MarkAF.py
===================================================================
--- trunk/src/workers/ImageProcessing/ImageProcessing/MarkAF.py	2010-07-08 13:13:29 UTC (rev 694)
+++ trunk/src/workers/ImageProcessing/ImageProcessing/MarkAF.py	2010-07-12 20:43:11 UTC (rev 695)
@@ -106,7 +106,7 @@
         output_img = deepcopy(image)
         if vmin is not None:
             output_img.attributes.update({'vmin':vmin, 'vmax':vmax})
-        mf_z = int(image.attributes['zid'][-2:])
+        mf_z = image.attributes['zid']
         slicess = [(slice(yt, yp), slice(xt, xp)) \
                    for yt, yp, xt, xp, z in zip(
             statistics['yt'].data, statistics['yp'].data,
@@ -125,7 +125,7 @@
         output_img = deepcopy(image)
         output_img.data = numpy.zeros(image.data.shape,
                                       dtype=image.data.dtype)
-        mf_z = int(image.attributes['zid'][-2:])
+        mf_z = image.attributes['zid']
         labelslicess = [(label, (slice(yt, yp), slice(xt, xp))) \
                        for label, yt, yp, xt, xp, z in zip(
             statistics['label'].data,
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 |