Search code examples
pythondm-script

Converting 32bit float DM4s to signed 16bit


I have a bunch of cryo and liquid cell dm4 images that are 32bit float, but the precision and the large values of 32bit are completely unnecessary, so we've decided to convert them to 16bit signed int.

I need to preserve the metadata structure that dm4 images have because the images still need to be openable in digital micrograph. So using hyperspy or ncempy is not an option since they can't write dm4 files.

I currently have a script to do this in dm-script, but it only takes in one directory at a time and doesn't know how to handle liquid cell data. And I am not good enough to do that.

I was wondering if I could do the same thing in the python interface in DM? Since I can manipulate the file structure and traverse the directories with easily with python.

The dm script I'm referring to is the on FELMI ZFE DigitalMicrograph Script Database slightly adjusted to allow for signed integers and not creating tiffs since they are not useful for us currently.

Edit: the dm-script works nicely for now, i am curious if there is a way to pass the source and output directory to my dm-script from the python script. That way i can do all the directory handling in python, and just call the dm-script one folder at a time.


Solution

  • Not sure if this is what you're after, but the script below shows how one recursively builds a file-list from all subfolders, filters it by extension, and then act on each of them.

    The current script will open all .dm4 files of a given folder and its subfolders, convert the image into sint16 and resave it with a prefixed name.

    However, you can very easily adjust the script by modifying the method ActOnFile.

    // Script class compiling a (filtered) TagList of filepaths from 
    // a folder. Optionally with recursion for subfolders
    Class CRecursiveFileList{
        TagGroup BuildList( object self, string path, string leadIn, string leadOut, number bSubfolders){
            tagGroup FileList = NewTagList()
            TagGroup allFiles = GetFilesInDirectory( path, 1 )
            number nFiles = allFiles.TagGroupCountTags()
            leadIn = StringToLower(leadIn)
            leadOut = StringToLower(leadOut)
            for ( number i=0; i<nFiles; i++ )
            {
                string file
                TagGroup entry
                allFiles.TagGroupgetIndexedTagAsTagGroup( i, entry )
                entry.TagGroupGetTagAsString( "Name", file )
                file = StringToLower(file)
                
                if ( len(leadIn)  > len(file) ) continue
                if ( len(leadOut) > len(file) ) continue
                if ( left(file,len(leadIn)) != leadIn ) continue
                if ( right(file,len(leadOut)) != leadOut ) continue
                
                FileList.TagGroupInsertTagAsString( Infinity(), PathConcatenate(path,file) )
            }
            if (bSubFolders)
            {
                TagGroup allFolders = GetFilesInDirectory( path, 2 )
                number nFolders = allFolders.TagGroupCountTags()
                for ( number i=0; i<nFolders; i++ )
                {
                    string folder
                    TagGroup entry
                    allFolders.TagGroupgetIndexedTagAsTagGroup( i, entry )
                    entry.TagGroupGetTagAsString( "Name", folder )
                    folder = StringToLower(folder)
                    TagGroup SubList = self.BuildList( PathConcatenate(path,folder), leadIn, leadOut, bSubfolders )
                    for ( number j=0; j<SubList.TagGroupCountTags(); j++)
                    {
                        string file
                        if ( SubList.tagGroupGetIndexedTagAsString(j,file))
                            FileList.TagGroupInsertTagAsString( Infinity(), file )
                    }
                }
            }
            return FileList
        }
        
        TagGroup Create( object self, string root, string LLin, string LLout, number incSubFolder ){
            TagGroup fullFileList
            if ( !DoesDirectoryExist( root )  || "" == root )
            {
                root = GetApplicationDirectory( "open_save", 0 )
                if ( !GetDirectoryDialog(NULL,"Select root path", root, root ) ) 
                    return fullFileList;
            }
        
            fullFileList = self.BuildList( root, LLin, LLout, incSubFolder );
            return fullFileList;
        }  
    }
    
    Class CActOnFileList{
        void ActOnFile( object self, string path ){
            // Do whatever you want with a file(path) here!
            if ( !DoesFileExist(path) ) {
                Result( "\n Not found: " + path )       // Skip with message
                // Throw( "File not found:\n" + path )  // or stop the script with error
                return
            }
            
            //Assuming it is an image, we open it 
            Image img := OpenImage(path)
            if ( !img.ImageIsValid() ) {
                Result( "\n Filt not an image: " + path )       // Skip with message
                // Throw( "File is not a valid image:\n" + path ) // or stop the script with error
                return
            }
            
            // We could show it...
            //img.ShowImage()
            
            // Instead, we convert it to 2-byte-integer and resave it with modifed name
            ConvertToShort(img)
            
            string newName = PathExtractDirectory(path,0) + "Conv_" + PathExtractBaseName(path,0) 
            img.SaveAsGatan(newName)
            
            Result("\n Converted & Saved: " + newName )
        
        }
    
        number PerformActionOnAllFilesInList( object self, TagGroup fileList, number bShowProgress ){
            number nFiles = fileList.TagGroupCountTags()
            for( number i = 0; i<nFiles; i++ ){
                if ( bShowProgress )
                    OpenAndSetProgressWindow( "Acting on file", (i+1) + " of " +  nFiles, "" )
                    
                string path
                if ( fileList.TagGroupGetIndexedTagAsString(i,path) )
                    self.ActOnFile(path)
            }
            CloseProgressWindow()
        }
    }
    
    string root = ""        // Leave "" to get a prompt
    string pre = ""         // Leave "" for no filter. Otherwise only paths which start with pre are kept
    string suf = ".dm4"     // Leave "" for no filter. Otherwise only paths which end with suf are kept
    number subfolder = 1    // Set "0" to only work on the specified folder and 1 to include all subfolders
    number showProgress = 1 // Set "1" to have a progress output (status bar)
    
    
    Alloc(CActOnFileList).PerformActionOnAllFilesInList( Alloc(CRecursiveFileList).Create(root, pre, suf, subfolder), showProgress )