如何将tif校准导入DM [英] how to import tif calibration into DM

查看:439
本文介绍了如何将tif校准导入DM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们需要处理DigitalMicrograph中来自FEI和Zeiss工具的SEM图像.它们存储为tif. DigitalMicrograph可以读取2d tif,但图像在X,Y方向上显示为未校准.是否有任何导入插件可以传输校准信息?另外,我可以想象校准可以直接从流中变为红色.有谁知道将偏移量存储在tif流中的偏移量的清晰主意吗?我对tif的组织不是很熟悉,并且知道存在一些变体.特别是,FEI和Zeiss的tif似乎有不同的组织.

We need to treat the SEM images from FEI and Zeiss tools in DigitalMicrograph. They are stored as tif. DigitalMicrograph can read 2D tif but images appear uncalibrated in X,Y directions. Is there any import plugIn that transfers the calibration information ? Alternatively, I can imagine that the calibration can be red directly from a stream. Has anyone a clear idea about the offset where such numbers are stored in a stream of tif? I am not very familiar with organization of tif and I know some variations exist. In particular, FEI and Zeiss tifs seems to be organized differently.

推荐答案

FEI和ZEISS似乎都将校准信息存储在它们自己的自定义ASCII文本标签中.遵循 TIFF格式规范(PDF),您可以轻松编写从TIFF中提取所有ASCII字段的脚本. 从那里开始,必须执行文本操作才能进行校准并将其设置为图像.

Both FEI and ZEISS seem to store the calibration info in their own, custom ASCII text tags. Following the TIFF Format specifications (PDF) one can easily write a script which extracts all ASCII fields from the TIFF. From there on, one has to perform text-manipulations to get to the calibrations and set them to the image.

下面的脚本使用以下信息对FEI和蔡司图像执行此操作:

The script below does this for both FEI and ZEISS images, using the following information:

FEI

尺寸信息在表格中的文本中:
[Scan]
PixelWidth=8.26823e-010
PixelHeight=8.26823e-010
这以[米]为单位指定像素大小

FEI

The size information is in the text in Form:
[Scan]
PixelWidth=8.26823e-010
PixelHeight=8.26823e-010
This specifies the pixel size in [meter]

尺寸信息在表格中的文本中:
AP_HEIGHT
Height = 343.0 nm
AP_WIDTH
Width = 457.3 nm
这指定了FOV大小.

The size information is in the text in Form:
AP_HEIGHT
Height = 343.0 nm
AP_WIDTH
Width = 457.3 nm
This specifies the FOV size.


在PasteBin上的

脚本.


Script on PasteBin.

// Auxilliary method for stream-reading of values
number ReadValueOfType(object fStream, string type, number byteOrder)
{
    number val = 0
    TagGroup tg = NewTagGroup()
    if ( type == "bool" )
    {
        tg.TagGroupSetTagAsBoolean( type, 0 )
        tg.TagGroupReadTagDataFromStream( type, fstream, byteOrder ) 
        tg.TagGroupGetTagAsBoolean( type, val )
    }
    else if ( type == "uint16" )
    {
        tg.TagGroupSetTagAsUInt16( type, 0 )
        tg.TagGroupReadTagDataFromStream( type, fstream, byteOrder ) 
        tg.TagGroupGetTagAsUInt16( type, val )
    }
    else if ( type == "uint32" )
    {
        tg.TagGroupSetTagAsUInt32( type, 0 )
        tg.TagGroupReadTagDataFromStream( type, fstream, byteOrder ) 
        tg.TagGroupGetTagAsUInt32( type, val )
    }
    else Throw("Invalid read-type:"+type)
    return val
}
    
string ExtractTextFromTiff( string path )
{
    string txt
    if ( !DoesFileExist(path) ) Throw("File not found.\n"+path)
    
    // Open Stream 
    number fileID = OpenFileForReading( path )
    object fStream = NewStreamFromFileReference(fileID,1)
    
    // Read data byte order. (1 = big Endian, 2= little Endian for Gatan)
    number val
    number byteOrder = 0
    val = fStream.ReadValueOfType( "uint16", byteOrder )
    byteOrder = ( 0x4949 == val  ) ? 2 : ( 0x4D4D == val ? 1 : 0 )
    //Result("\n TIFF endian:"+byteOrder)
    
    // Verify TIFF image
    val = fStream.ReadValueOfType( "uint16", byteOrder )
    if ( val != 42 ) Throw( "Not a valid TIFF image" )
    
    // Browse all directories
    number offset = fStream.ReadValueOfType( "uint32", byteOrder )
    
    while( 0 != offset )
    {
        fStream.StreamSetPos( 0, offset ) // Start of IFD
        number nEntries = fStream.ReadValueOfType( "uint16", byteOrder )
        for ( number e=0;e<nEntries;e++)
        {
            number tag        = fStream.ReadValueOfType( "uint16", byteOrder )
            number typ        = fStream.ReadValueOfType( "uint16", byteOrder )
            number count      = fStream.ReadValueOfType( "uint32", byteOrder )
            number dataOffset = fStream.ReadValueOfType( "uint32", byteOrder )
            //Result("\n entry # "+e+": ID["+tag+"]\ttyp="+typ+"\tcount="+count+"\t offset @ "+dataOffset)
            if ( 2 == typ ) // ASCII
            {
                number currentPos = fStream.StreamGetPos()
                fStream.StreamSetPos( 0, dataOffset )
                string textField = fStream.StreamReadAsText( 0, count )
                txt+=textField
                fStream.StreamSetPos( 0, currentPos )
            }   
        }
        offset = fStream.ReadValueOfType( "uint32", byteOrder ) // this is 0000 for the last directory according to spec
    }
    
    return txt
}

String TruncWhiteSpaceBeforeAndAfter( string input )
{
    string work = input
    if ( len(work) == 0 ) return ""
    while ( " " == left(work,1) )
    {
        work = right( work, len(work) - 1 )
        if ( len(work) == 0 ) return "" 
    }
    while ( " " == right(work,1) )
    {
        work = left( work, len(work) - 1 )
        if ( len(work) == 0 ) return "" 
    }
    return work
}


// INPUT:  String with line-wise information
// OUTPUT: TagGroup
// Assumptions:  
//  - Groups are specified in a line in the format:             [GroupName]
//  - The string contains information line-wise in the format:  KeyName=Vale
TagGroup CreateTagsFromString( string input )
{
    TagGroup tg = NewTagGroup()
    string work = input
    
    string eoL          = "\n"
    string GroupLeadIn  = "["
    string GroupLeadOut = "]"
    string keyToValueSep= "="
    string groupName = ""
    
    number pos = find(work,eoL )
    while( -1 != pos )
    {
        string line = left(work,pos)
        work = right(work,len(work)-pos-len(eoL))
        number leadIn  = find(line,GroupLeadIn)
        number leadOut = find(line,GroupLeadOut)
        number sep = find(line,keyToValueSep)
        if ( ( -1 < leadIn ) && ( -1 < leadOut ) && ( leadIn < leadOut ) ) // Is it a new group? "[GROUPNAME]"
        {
            groupName = mid(line,leadIn+len(GroupLeadIn),leadOut-leadIn-len(GroupLeadOut))
            groupName = TruncWhiteSpaceBeforeAndAfter(groupName)
        }
        else if( -1 < sep )                                                 // Is it a value? "KEY=VALUE" ?
        {
            string key  = left(line,sep)
            string value= right(line,len(line)-sep-len(keyToValueSep))
            key   = TruncWhiteSpaceBeforeAndAfter(key)
            value = TruncWhiteSpaceBeforeAndAfter(value)
            string tagPath = groupName + ( "" == groupName ? "" : ":" ) + key
            tg.TagGroupSetTagAsString( tagPath, value )
        }
        pos = find(work,eoL)        
    }
    return tg
}

void ImportTIFFWithTags()
{
    string path = GetApplicationDirectory("open_save",0)
    if (!OpenDialog(NULL,"Select TIFF file",path, path)) exit(0)
    
    string extractedText = ExtractTextFromTiff(path)
    /*
    if ( TwoButtonDialog("Show extracted text?","Yes","No") )
        result(extractedtext)
    */
    
    tagGroup infoAsTags = CreateTagsFromString(extractedText )
    /*
    if ( TwoButtonDialog("Output tagstructure?","Yes","No") )
        infoAsTags.TagGroupOpenBrowserWindow(path,0)
    */
    
    // Import data and add info-tags
    image imported := OpenImage(path)
    imported.ImageGetTagGroup().TagGroupSetTagAsTagGroup("TIFF Tags",infoAsTags)
    imported.ShowImage()

    // Calibrate image, if info is found
    // It seems FEI stores this value as [m] in the tags PixelHeight and PixelWidth
    // while ZEISS images contain the size of the FOV in the tags "Height" and "Width" as string including unit
    number scaleX = 0
    number scaleY = 0
    string unitX 
    string UnitY
    string hStr
    string wStr
    if ( imported.GetNumberNote( "TIFF Tags:Scan:PixelWidth", scaleX ) )
    {
        unitX = "nm"
        scaleX *= 1e9
    }
    if ( imported.GetNumberNote( "TIFF Tags:Scan:PixelHeight", scaleY ) )
    {
        unitY = "nm"
        scaleY *= 1e9
    }
    if ( imported.GetStringNote( "TIFF Tags:Width", wStr ) )
    {
        number pos = find( wStr, " " )
        if ( -1 < pos )
        {
            scaleX = val( left(wStr,pos) )
            scaleX /= imported.ImageGetDimensionSize(0)
            unitX  = right( wStr, len(wStr)-pos-1 )
        }
    }
    if ( imported.GetStringNote( "TIFF Tags:Height", hStr ) )
    {
        number pos = find( hStr, " " )
        if ( -1 < pos )
        {
            scaleY = val( left(hStr,pos) )
            scaleY /= imported.ImageGetDimensionSize(1)
            unitY  = right( hStr, len(hStr)-pos-1 )
        }
    }
    if ( 0 < scaleX )
    {
        imported.ImageSetDimensionScale(0,scaleX)
        imported.ImageSetDimensionUnitString(0,unitX)
    }
    if ( 0 < scaleY )
    {
        imported.ImageSetDimensionScale(1,scaleY)
        imported.ImageSetDimensionUnitString(1,unitY)
    }
}
ImportTIFFWithTags()

这篇关于如何将tif校准导入DM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆