How to use dm script to realize the "save display as" function? - dm-script

It is easy to save the false color image to BMP or JPG by using "save display as" function in menu. But it fails to save a image stack as the seperated images with the displaying color. "save display as" only saves the front image of the stack. I could not click hundreds of times to save the whole stack! But I do not find the corresponding script function in the dm manual. How to realize it?

The command you're looking for is ImageDisplayGetExportImage() and there is actually an
example script in the F1 help documentation of latest GMS for that:
But the command - same as the menu item - will only act on the actual display, so you still need to iterate over the displayed layers by script using ImageDisplaySetDisplayedLayers()
So your script will be something like the following example:
image test:=RealImage("Stack",4,100,100,10)
test=sin(icol/iwidth*Pi()*2) * cos(itheta*iplane)
test.ShowImage()
imagedisplay disp = test.ImageGetImageDisplay(0)
disp.ImageDisplaySetColorTableByName("Rainbow")
number nz = test.ImageGetDimensionSize(2)
for( number z=0; z<nz; z++){
disp.ImageDisplaySetDisplayedLayers(z,z)
imageDisplay newdisp
image asDisplayedRGB := disp.ImageDisplayGetExportImage( 7, newdisp )
asDisplayedRGB.SetName( test.GetName() + "_" + z )
asDisplayedRGB.ShowImage()
}
EGUPerformActionWithAllShownImages("arrange")

I hope this is what you are looking for. The shown script allows you to save all images in the current workspace to a directory. You can specify the format, the directory and the name pattern. (It got a bit longer than I expected):
TagGroup formats = NewTagGroup();
formats.TagGroupSetTagAsString("Gatan Format", "dm4");
formats.TagGroupSetTagAsString("Gatan 3 Format", "dm3");
formats.TagGroupSetTagAsString("GIF Format", "gif");
formats.TagGroupSetTagAsString("BMP Format", "bmp");
formats.TagGroupSetTagAsString("JPEG/JFIF Format", "jpg");
formats.TagGroupSetTagAsString("Enhanced Metafile Format", "emf");
formats.TagGroupSetTagAsString("TIFF Format", "tif");
formats.TagGroupSetTagAsString("PCX Format", "pcx");
class FormatDialog : UIFrame{
TagGroup format_select;
number FormatDialogGetSelectedFormat(object self){
if(format_select.TagGroupIsValid()){
return format_select.DLGGetValue();
}
else{
return -1;
}
}
object init(object self){
TagGroup dlg, dlg_items;
dlg = DLGCreateDialog("Select the format", dlg_items);
dlg_items.DLGAddElement(DLGCreateLabel("Please select the export format"));
format_select = DLGCreateChoice(0);
format_select.DLGIdentifier("format_select");
for(number i = 0; i < formats.TagGroupCountTags(); i++){
string text;
formats.TagGroupGetIndexedTagAsString(i, text);
text = formats.TagGroupGetTagLabel(i) + " (" + text + ")";
format_select.DLGAddChoiceItemEntry(text);
}
dlg_items.DLGAddElement(format_select);
self.super.init(dlg);
return self;
}
}
object format_dialog = alloc(FormatDialog).init();
if(format_dialog.pose()){
number format = format_dialog.FormatDialogGetSelectedFormat();
if(format < 0 || format >= formats.TagGroupCountTags()){
throw("Invalid format is selected");
}
string save_format = formats.TagGroupGetTagLabel(format);
string save_extension;
formats.TagGroupGetIndexedTagAsString(format, save_extension);
string save_dir;
if(GetDirectoryDialog("Please select the path to save to", GetApplicationDirectory("open_save", 1), save_dir)){
string save_name;
if(GetString("Please set the file name (without extension). A number will be added to the end automatically.", "file_", save_name)){
for(number i = 0; i < CountImageDocuments(); i++){
ImageDocument doc = GetImageDocument(i);
doc.ImageDocumentSaveToFile(save_format, PathConcatenate(save_dir, save_name + i + "." + save_extension));
}
OKDialog("Saved " + CountImageDocuments() + " files.");
}
}
}
Note that you can add that to DigitalMicrographs menus. Save the posted code as a file, then use File > Install Script File and add the script to any of your existing menus or a new menu.

Related

How to exclude certain images from autosave in Gatan Digital Micrograph (GMS) in DM-script

I am trying to mimic the autosave function in GMS v3 so that I can use in version 1 and 2. I would like to first acknowledge that the main bulk of the script originates from Dr Bernhard Schaffer's "How to script... Digital Micrograph Scripting Handbook". I have modified it a bit, so that any new image recorded by the camera can be autosave into the file. However, I met some problems because if I decide to click on live-view image and move the image around, or using live-fft, the live view image or the FFT image will be saved as well. One of the ideas I have is to use the taggroup information such as the "Acquisition:Parameters:Parameter Set Name" because for live view or live-FFT, this would be either in search or focus mode. Another idea is to use the document ID e.g iDocID = idoc.ImageDocumentGETID() to locate the ID of the live image. However, i am clueless then how to use this information to exclude them from autosaving. Can anyone point to me how i can proceed with this script?
Below is the script
Class PeriodicAutoSave : Object
{
Number output
PeriodicAutoSave(Object self) Result("\n Object ID"+self.ScriptObjectGetID()+" created.")
~PeriodicAutoSave(Object self) Result("\n Object ID"+self.ScriptObjectGetID()+" destroyed")
Void Init2(Object self, Number op)
output=op
Void AutoSave_SaveAll(Object self)
{
String path, name, targettype, targettype1, area, mag, mode, search, result1
ImageDocument idoc
Number nr_idoc, count, index_i, index, iDocID, iDocID_search
path = "c:\\path\\"
name = "test"
targettype=="Gatan Format (*.dm4)"
targettype1 = "dm4"
If (output) Result("\n AutoSave...")
nr_idoc = CountImageDocuments()
For (count = 1; count<nr_idoc; count++)
{
idoc = GetImageDocument(count) //imagedocument
index = 1 // user decide the index to start with
index_i= nr_idoc - index
If (idoc.ImageDocumentIsDirty())
{
idoc = getfrontimagedocument()
iDocID = idoc.ImageDocumentGetID()
TagGroup tg = ImageGetTagGroup(idoc.ImageDocumentGetImage(0)) // cannot declare an 'img' for this line as it will prompt an error?
tg.TagGroupGetTagAsString("Microscope Info:Formatted Indicated Mag", mag)
Try{
{
idoc.ImageDocumentSavetoFile( "Gatan Format", path+index_i+"-"+name+"-"+mag+".dm4")
idoc.ImageDocumentSetName(index_i + "-"+name+"-"+mag+".dm4")
idoc.ImageDocumentClean()
}
If (Output) Result("\n\t saving: "+idoc.ImageDocumentGetCurrentFile())
}
Catch{
Result("\n image cannot be saved at the moment:" + GetExceptionString())
Break
}
Result("\ Continue autosave...")
}
}
}
}
Void LaunchAutoSave()
{
Object obj = Alloc(PeriodicAutoSave)
obj.Init2(2)
Number task_id = obj.AddMainThreadPeriodicTask("AutoSave_SaveALL",6)
//Sleep(10)
while(!shiftdown()) 1==2
RemoveMainThreadTask(task_id)
}
LaunchAutoSave()
thank you very much for your pointers! I have tried and it works very well with my script. as the 'TagGroupDoesTagExist' only refers to the taggroup, I modified further to include the tags I want to filter e.g "Search" or "Focus" and it seems to work well. The script that I modified to your existing ones is as below :
If (idoc.ImageDocumentIsDirty())
{
//now find out what is a filter condition and skip if it is true
skip = 0
TagGroup tg = idoc.ImageDocumentGetImage(0).ImageGetTagGroup()
tg.TagGroupGetTagAsString("Microscope Info:Formatted Indicated Mag", mag)
tg.TagGroupGetTagAsString("Acquisition:Parameters:Parameter Set Name", mode)
skip = tg.TagGroupDoesTagExist("Acquisition:Parameters:Parameter Set Name")
if(skip && (mode == "Search" || mode== "Focus")) continue
Your idea of filtering is a good one, but there is something strange with your for loop.
in
nr_idoc = CountImageDocuments()
For (count = 1; count<nr_idoc; count++)
{
idoc = GetImageDocument(count) //imagedocument
you iterate over all currently open imageDocuments (except the first one!?) and get them one by one, but then in
If (idoc.ImageDocumentIsDirty())
{
idoc = getfrontimagedocument()
you actually get the front-most (selected) document instead each time. Why are you doing this?
Why not go with:
number nr_idoc = CountImageDocuments()
for (number count = 0; count<nr_idoc; count++)
{
imagedocument idoc = GetImageDocument(count)
If (idoc.ImageDocumentIsDirty())
{
// now find out what is a filter condition and skip if it is true
number skip = 0
TagGroup tg = idoc.ImageDocumentGetImage(0).ImageGetTagGroup()
skip = tg.TagGroupDoesTagExist("Microscope Info:Formatted Indicated Mag")
if (skip) continue
// do saving
}
}

How to name tabs in pdf export to xls

I have a PDF form that has many form fields. My requirement is to export the form data (some of it anyway) into an excel (xls) format on a network drive that is being picked up and used by another process (that I do not have access or code to change) to load into a database using Acrobat Javascript when a button on the PDF is clicked. As this is a distributed form and the network drive is common, it did not make sense to setup ODBC connections to the database nor did I have access to do so.
The issues I am having are:
I need to specifically name the Worksheet so that the process correctly processes the xls file.
I need to save the information to the network drive without prompting the user, which the code below does.
The fieldNames seem to be losing spaces when they export to xls.
So far nothing I tried has worked nor do any of the references I have gone though provide such information. I can push data into a .csv and .txt files and have tried creating a new Report something like the following:
var rep = new Report();
var values = "";
...
rep.writeText(values);
var docRep = rep.open("myreport.pdf");
docRep.saveAs("/c/temp/Upload.txt","com.adobe.acrobat.plain-text")
docRep.closeDoc(true);
app.alert("Upload File Saved", 3);
but it only allows the .txt extension not the xls or csv extension. I managed to export the csv in another way.
Below is a small snippet of my code:
var fieldNames = [];
var result ="";
fieldNames.push("Inn Code");
fieldValues.push('"' + this.getField("Hotel Info Inn Code").value + '"');
fieldNames.push("Business Unit");
fieldValues.push('"' + this.getField("Hotel Info Business Unit").value + '"');
for ( var i=0; i < fieldNames.length; i++ ) {
result += (fieldNames[i] + "\t");
}
for ( var i=0; i < fieldValues.length; i++ ) {
result += (fieldValues[i] + "\t");
}
this.createDataObject({cName: "Upload.xls", cValue: cMyC});
this.exportDataObject({cName: "Upload.xls", nLaunch: 0});
Any help or suggestions provided would be greatly appreciated!
Update (For anyone else who encounters this need).
I determined that the tab name using the method above is the same as the save name. The other issue I encountered was that the xls file was really a csv with an xls extension. To resolve this I decided to export an csv I am formatting or a text file and an external process to reformat the file as an xls.
var fieldNames = [];
var fieldValues = [];
var result = '';
// FIELD VALUES
fieldNames.push('"Column Name 1"');
fieldValues.push('\r\n' + '"' + this.getField("Field Name 1").value + '"');
fieldNames.push('"Column Name 2"');
fieldValues.push('"' + this.getField("Field Name 2").value + '"');
for ( var i=0; i < fieldNames.length; i++ ) {
if (i != fieldNames.length-1){
result += (fieldNames[i] + ",");
} else {
result += (fieldNames[i]);
}
}
for ( var i=0; i < fieldValues.length; i++ ) {
if (i != fieldValues.length-1){
result += (fieldValues[i] + ",");
} else {
result += (fieldValues[i]);
}
}
I used the following to output a csv file:
this.createDataObject('UploadFile.csv', result);
this.exportDataObject({ cName:'UploadFile.csv', nLaunch:'0'});
The issue is that this prompts the user where to save the file and I wanted a silent specific location so I wound up doing the following in place of the create and export object above to output a txt file silently without prompting the user:
var rep = new Report();
rep.writeText(result);
var docRep = rep.open("myreport.pdf");
docRep.saveAs("/c/temp/UploadFile.txt","com.adobe.acrobat.plain-text")
docRep.closeDoc(true);
You will have to go into Edit > Preferences > Security (Enhanced) then choose the output folder (C:\Temp) in my case to output silently if you chose to employ this method.

Photoshop action for changing text number and saving with variable

I have a lot of graphic buttons that I need to make. I have 2 layers
TEXT (This is going to be numbers 1-48 for instance)
White Button image
I'm not sure how to go about writing this action or if I need a script. I need to have the text layer start at 1 and follow this progression.
save file w1.png (this yields a png with a button labeled with a "1"
change text to 2
save file w2.png (this yields a png with a button labeled with a "2"
change text to 3
. . . .
ect. . .all the way to 48. So this would make 48 images automatically. Can this be done with "actions" or do I need to learn scripting?
Save
You'll need a script for this, but it's going to be a rather simple one
function main() {
//this just checks if you have a text layer selected
try {
var textLayer = activeDocument.activeLayer.textItem
} catch (e) {
alert("active layer isn't a text layer");
return
};
var loops = 48,
pngSaveOptions = new PNGSaveOptions(),
outputFolder = Folder.selectDialog('', Folder.desktop); //this will ask for an output folder
for (var i = 0; i < loops; i++) {
var myNum = i + 1;
textLayer.contents = myNum; //this will change layer contents to number only. if you need some text here, write it in quotes like textLayer.contents = "my text" + myNum;
activeDocument.saveAs(new File(outputFolder + "/w" + myNum + ".png"), pngSaveOptions, true, Extension.LOWERCASE);
}
}
app.activeDocument.suspendHistory("temp", "main()");

Can one get a list of fonts available for text annotations in DM scripting?

One can create text annotations on image displays via the function NewTextAnnotation and then change the font via the method ComponentSetFontFaceName. However to do so successfully, one must provide the full name of the desired font as a string and one must already know that it is available on the current system. If one specifies an unavailable font, some default font seems to be chosen and no exception or error message is posted.
Is there any way to get a list of available fonts within a DM script or to determine whether a specific named font is actually available?
Interesting task!
There is no actual script command to do this, and the list of installed font-names is populated by the OS.
However, using Powershell and the script command LaunchExternal() one can construct a workaround.
After some trial and error, I think I got it working by the following script:
void WriteFontListToDisk( string fileName )
{
String PSscript
PSscript += "[System.Reflection.Assembly]::LoadWithPartialName('System.Drawing');"
PSscript += "(New-Object System.Drawing.Text.InstalledFontCollection).Families "
PSscript += " | out-file -encoding ASCII " + fileName // Need to specify ASCII here!
String callString
callString += "powershell"
//callString += " -NoExit" // Keep Powershell open
callString += " -Command &{ "
callString += PSscript
callString += " }"
LaunchExternalProcess( callString, 5 )
}
TagGroup ReadFontListFromFile( string fileName )
{
TagGroup tg = NewTagList()
if ( !DoesFileExist( fileName ) ) Throw( "Font list file not found:\n" + fileName )
number fileID = OpenFileForReading( fileName )
object fileStream = NewStreamFromFileReference( fileID, 1 )
result("\n SIZE:" + fileStream.StreamGetSize() )
// Output format is
// #1:(empty)
// #2: Name
// #3: ----
// #4+: FontNames
string line
for( number i=0;i<3;i++) fileStream.StreamReadTextLine( 0, line )
number inc = 0
while( fileStream.StreamGetPos() != fileStream.StreamGetSize() )
{
if ( !fileStream.StreamReadTextLine( 0, line ) ) break;
tg.TagGroupInsertTagAsString( Infinity(), line )
if ( ShiftDown() ) exit(0)
}
return tg
}
TagGroup GetFontList()
{
TagGroup tg = NewTagGroup()
string fileName = "C:\\FontNamesList.txt"
if ( DoesFileExist( fileName ) ) DeleteFile( fileName )
WriteFontListToDisk( fileName )
tg = ReadFontListFromFile( fileName )
if ( DoesFileExist( fileName ) ) DeleteFile( fileName )
return tg
}
GetFontList().TagGroupOpenBrowserWindow( "Fonts" , 0 )
It is worthwhile to note that PowerShell by default streams text output as UNICODE and that does not work well with text-import in DM. However, this question was helpful, and the script above sets the output to ASCII. One issue though is, that in doing so some characters might be lost and it might be needed to carefully check the output font-list.

How to save images automatically after setting up a path?

I want to save my images automatically, but I don't know how to set it in DM. My script is as follows:
Image img
img.GetFrontImage()
string name
if ( GetString( "Enter Name of Sample", "Hello!", name ))
result( "\nThe Name Of Sample is "+name)
string path
if ( GetDirectoryDialog("select path","",path) )
result("\nSelected path is:"+path)
While( img.ImageIsValid() )
{
For( number i=i; i<1000000;i++ )
{
img.SetName(name+i)
img.SaveImage(name+i)
img := FindNextImage(img)
}
}
It seems the main thing you are missing is a line that creates a full pathname from the combination of the destination directory path and the name for each image. So in addition to the changes suggested in the answer by BmyGuest, you should add a call to PathConcatenate, as follows:
number i = 1
While( img.ImageIsValid() )
{
img.SetName(name+i)
string filepath = path.PathConcatenate(name+i)
img.SaveAsGatan(filepath)
img := FindNextImage(img)
i++
}
The script you've written will not save anything, but most likely produce an error.
In the For-loop you 1000000x get the "next" image to save, but when you reach the end the "next" image is invalid.
Therefore, the next iteration will throw an error at img.SetName, because img is not a valid image at that moment.
What you want to do is something like the following:
number i = 1
While( img.ImageIsValid() )
{
img.SetName(name+i)
img.SaveAsGatan(name+i)
img := FindNextImage(img)
i++
}