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. |