what is the command to add a Y coordinate name - dm-script

When we import the CSV line plot file to DM, what is the command /code to add a Y coordinate name? Such as intensity or counts etc.
string filename
dircontents.taggroupgettagasstring("["+i+"]:Name", filename)
string extension=pathextractextension(filename,0)
if(extension!="csv" && extension!="CSV" && extension!="txt" && extension!="TXT")
{
result("\nSkipped file "+filename+". Files must be .csv or .txt")
continue
}
string thisfilepath=pathconcatenate(directory, filename)
image array=ReadandDisplayCSV(thisfilepath, headerline)
drawlineplot(array, headerline, filename, IncludeError)

The commands - as documented in the F1 help at the end of the "image" chapter - are
ImageSetIntensityScale
ImageSetIntensityOrigin
ImageSetIntensityUnitString
You use them as in the following example:
image linePlot := realImage( "Spectrum", 4, 200 )
linePlot = cos( icol/iwidth * 5 * Pi() ) + random()*0.1
linePlot.ShowImage()
OKDialog( "Add X calibration" )
linePlot.ImageSetDimensionCalibration( 0, 100, 0.5, "eV" , 0 )
OKDialog( "Add intensity calibration" )
linePlot.ImageSetIntensityScale( 0.5 )
linePlot.ImageSetIntensityOrigin( 100 )
linePlot.ImageSetIntensityUnitString( "counts" )

Related

How to set starting and ending point for line projection in DM script

I am trying to draw line projection for an image . The line 4 in the code below sy/2 represents the length of projection (here is the half image range). But how to set the starting point or ending point with scripting? For example, I want to draw the line projection, from 1/4 image range to 3/4 image range. Any suggestions?
image src := getfrontimage()
number sx,sy
src.GetSize(sx,sy)
image line_projection := RealImage( "Vertical", 4, sy/2 )
line_projection[irow,0] += src
line_projection *= 1/sx
While using intrinsic variables (icol,irow,...) for iterative summing was the fasted method in GMS 1, this is no longer true for newer versions that utilize multi-threaded code, as demonstrated by the following example:
// various ways to sum a subsection of an image
number sx = 4096, sy = 4096
number startx = 0.2, starty = 0.2
number endx = 0.8, endy = 0.4
// Coordinates of cut
number t = trunc(starty*sy), l = trunc(startx*sx), b = trunc(endy*sy), r = trunc(endx*sx)
image test := realImage( "Test", 4, sx, sy )
test = sin( icol/iwidth * 20*Pi()) + cos( itheta * iradius/iwidth * 50)
test= sin( icol/iwidth * 20*Pi())
test.ShowImage()
ROI marker = NewROI()
marker.ROISetLabel( "Section" )
marker.ROISetRectangle( t, l, b, r )
marker.ROISetVolatile( 0 )
test.ImageGetImageDisplay(0).ImageDisplayAddRoi( marker )
//OKDialog( "Performing vertical sum with various methods now." )
number h = b - t
number w = r - l
ClearResults()
number ts, te, tps = GetHighResTicksPerSecond()
// using intrinsic variables
image sumImg1 := RealImage( "Sum intrinsic", 4, w )
ts = GetHighResTickcount()
sumImg1[icol, 0] += test[t,l,b,r];
te = GetHighResTickcount()
sumImg1.ShowImage()
result("\n Summing using intrinisic variables: " + (te-ts)/tps + " sec")
// using for-loop of slice
image sumImg2 := RealImage( "Sum with slice", 4, w )
ts = GetHighResTickcount()
for( number i=0; i<h; i++)
sumImg2 += test.slice1(0,i,0, 0,w,1)
te = GetHighResTickcount()
sumImg2.ShowImage()
result("\n Summing using for-loop with slice : " + (te-ts)/tps + " sec")
// using project of slice
image sumImg3 := RealImage( "Sum with project", 4, w )
ts = GetHighResTickcount()
sumImg3 = test[t,l,b,r].project( 1 )
te = GetHighResTickcount()
sumImg3.ShowImage()
result("\n Summing using project on section : " + (te-ts)/tps + " sec")
You can use slicing to only look at the image area you are interested in. For "clipping" the source to the interesting part use img[y1, x1, y2, x2].
image src := getFrontImage();
number width, height;
src.GetSize(width, height);
number start_y = 1/4 * height;
number end_y = 3/4 * height;
image line_projection := RealImage("Vertical", 4, width);
line_projection[icol, 0] += src[start_y, 0, end_y, width];
line_projection *= 1/(height/2);
line_projection.ShowImage();

Can one define a one dimensional image inline?

I would like to describe a very simple image (really a vector) of length 2, like (1,2) for the purpose of some linear algebra.
The following creates a two dimensional image with a y axis of length 1:
image a := [2,1]: {
{1, 2}
}
MatrixPrint(a)
This outputs
{
{1, 2}
}
How would I in a similar fashion output this instead?
{123,45}
Additionally, if I had image of arbitrary shape (a, b), how can I slice it to extract a one dimensional image at a value n, either along the x or y axes? (Extracting a line profile along one of the image axes)
In your example you do define a 2D image, so you get a 2D output. If the image really would be 1D, your output would be 1D, i.e.
image a := [2]: {123, 45}
MatrixPrint(a)
So your second question actually is the answer to your first: You need to do a 1D slice of the data, which you can do with the command slice1() as follows:
image a := [2,1]: {
{123, 45}
}
MatrixPrint( a.slice1(0,0,0,0,2,1) )
Note some peculiarities of the command:
The command always assume the input is 3D, so the first 3 parameters are the start-index triplet x/y/z even if it is just 2D or 1D data.
the 2nd triplet specifies the sampling of the slice. First the dimensions index (0=x) then the number of sampling steps (2) and then the stepsize (1)
Similar slice commands exist for 2D slices, 3D slices and nD Slices from nD data.
The matrixPrint command only outputs to the results window. There is no way to reroute this to some string. However, you can easily make yourself a method that would do that (albeit not very fast for big data):
string VectorPrint( image img, string FormatStr, number maxNum )
{
if ( !img.ImageIsValid() ) return "{invalid}"
if ( 1 != img.ImageGetNumDimensions() ) return "{not 1D}"
string out = "{ "
number nx = img.ImageGetDimensionSize(0)
if (( nx <= maxNum ) || ( maxNum <= 2) )
{
for( number i=0; i<min(nx,maxNum); i++)
out += Format( sum(img[0,i]), FormatStr ) + ", "
out = out.left( out.len() - 2 )
}
else
{
for( number i=0; i<maxNum-1; i++)
out += Format( sum(img[0,i]), FormatStr ) + ", "
out = out.left( out.len() - 2 ) + ", ... , "
out += Format( sum(img[0,nx-1]), FormatStr )
}
out += " }"
return out
}
image a := [10,4]: {
{1,2,3,4,5,6,7,8,9,10},
{123, 45, 12.3, -12, 55, 1.2, 9999, 89.100, 1e-10, 0},
{0,0,0,0,0,0,0,0,0,0},
{1,2,3,4,5,6,7,8,9,10}
}
// Slice 2D image to 1D image at n'th line
number n = 1
image line := a.slice1(0,n,0,0,a.ImageGetDimensionSize(0),1)
// Printout with given number format and a maximum number of entries
string fStr = "%3.1f"
number maxN = 3
Result( "\n "+VectorPrint( line, fStr, maxN ) )

the command to delete a slice of a line plot

search it in the help document, could not find it.
is something like: LinePlotImageDisplayDeleteSlices(LinePlotImageDisplay lpid)
Delete.LinePlotImageDisplayGetSlice ?
Thanks,
you are seeking
Boolean ImageDisplayDeleteSliceWithId( ImageDisplay id, ScriptObject slice_id )
used in combination with
ScriptObject ImageDisplayGetSliceIdByIndex( ImageDisplay id, Number slice_index )
Example copied from the F1 help documentation of GMS 3.3:
image CreateRandomSpectrum( number sx )
{
image img := RealImage( "Spectrum", 4, sx )
number fac = Random() * 3
number off = Random() * 10
number mag = Random() * 3
img = mag * sin( ( off + fac * icol / iwidth ) * Pi() )
return img
}
imageDisplay CreateAndShowMultiSlice( number nSlice, number sx )
{
image firstImg := CreateRandomSpectrum(100)
firstImg.ShowImage()
imageDisplay disp = firstImg.ImageGetImageDisplay(0)
for( number i = 1; i<nSlice; i++ )
disp.ImageDisplayAddImage( CreateRandomSpectrum(100), "" )
disp.LinePlotImageDisplaySetLegendShown( 1 )
return disp
}
void DemoRemoveSlice()
{
imageDisplay disp = CreateAndShowMultiSlice(5,100)
OKDialog( "Now remove 2nd slice" )
object id = disp.ImageDisplayGetSliceIDByIndex( 2 )
disp.ImageDisplayDeleteSliceWithId( id )
}
DemoRemoveSlice()

Identifying Peaks from Line Profile

I would like to ask if it is possible to locate the position of every maxima and minima of an intensity profile on DM.
How do I come up with a simple script that identifies the positions of the peaks in the example below?
Here's a screenshot of line intensity profile of a STEM image along the Y-direction:
If you want to filter for "strict" local maxima, then you can easily do this with image expressions and the conditional "tert" operator. The following example illustrates this:
image CreateTestSpec( number nChannels, number nPeaks, number amp, number back )
{
image testImg := RealImage( "TestSpec", 4, nChannels )
testImg = amp * cos( PI() + 2*PI() * nPeaks * icol/(iwidth-1) )
testImg += back
testImg = PoissonRandom( testImg )
return testImg
}
image FilterLocalMaxima1D( image spectrumIn, number range )
{
image spectrumOut := spectrumIn.ImageClone()
for( number dx = -range; dx<=range; dx++ )
spectrumout *= ( spectrumIn >= offset(spectrumIn,dx,0) ? 1 : 0 )
spectrumout.SetName("Local maxima ("+range+") filtered")
return spectrumOut
}
image test1 := CreateTestSpec(256,10,1000,5000)
image test2 := FilterLocalMaxima1D(test1,3)
test1.ShowImage()
test2.ShowImage()
However, considering noise (also in your example image), you might want to perform fits around these "local maxima" to ensure you're really getting what you want. The data from above is then only the starting point for that.
Also: Sometimes you can get away with first averaging your data and then finding the local maxima, instead of doing real data fitting in each peak. This works in particular, if you "know" the width of your real peaks rather well.
This would be the example:
image CreateTestSpec( number nChannels, number nPeaks, number amp, number back )
{
image testImg := RealImage( "TestSpec", 4, nChannels )
testImg = amp * cos( PI() + 2*PI() * nPeaks * icol/(iwidth-1) )
testImg += back
testImg = PoissonRandom( testImg )
return testImg
}
image FilterLocalMaxima1D( image spectrumIn, number range )
{
image spectrumOut := spectrumIn.ImageClone()
for( number dx = -range; dx<=range; dx++ )
spectrumout *= ( spectrumIn >= offset(spectrumIn,dx,0) ? 1 : 0 )
spectrumout.SetName("Local maxima ("+range+") filtered")
return spectrumOut
}
image FilterLocalMaxima1DAveraged( image spectrumIn, number range )
{
image avSpectrum := spectrumIn.ImageClone()
avSpectrum = 0
for( number dx = -range; dx<=range; dx++ )
avSpectrum += offset(spectrumIn,dx,0)
avSpectrum *= 1/(2*range+1)
image spectrumOut := spectrumIn.ImageClone()
for( number dx = -range; dx<=range; dx++ )
spectrumout *= ( avSpectrum >= offset(avSpectrum,dx,0) ? 1 : 0 )
spectrumout.SetName("Local maxima ("+range+") filtered, average")
return spectrumOut
}
image test1 := CreateTestSpec(256,10,1000,5000)
image maxPeaks := FilterLocalMaxima1D(test1,3)
image maxPeaksAv := FilterLocalMaxima1DAveraged(test1,3)
test1.ShowImage()
test1.ImageGetImageDisplay(0).ImageDisplayAddImage( maxPeaks, "local max" )
test1.ImageGetImageDisplay(0).ImageDisplayAddImage( maxPeaksAv, "local max from Average" )
test1.ImageGetImageDisplay(0).LinePlotImageDisplaySetSliceComponentColor( 0, 1, 0.7, 0.7, 0.7 )
test1.ImageGetImageDisplay(0).LinePlotImageDisplaySetSliceDrawingStyle( 1, 2)
test1.ImageGetImageDisplay(0).LinePlotImageDisplaySetSliceComponentColor( 1, 1, 1, 0, 0 )
test1.ImageGetImageDisplay(0).LinePlotImageDisplaySetSliceTransparency( 1, 1, 0.7 )
test1.ImageGetImageDisplay(0).LinePlotImageDisplaySetSliceDrawingStyle( 2, 2)
test1.ImageGetImageDisplay(0).LinePlotImageDisplaySetSliceComponentColor( 2, 1, 0, 1, 0 )
test1.ImageGetImageDisplay(0).LinePlotImageDisplaySetSliceTransparency( 2, 1, 0.7 )
The easiest way is to use 1-point (or 2-point) neighborhood to decide, whether center is minimum (maximum). See pseudo code below:
// assume 0 <= x <= maxX, y(x) is value at point x, radius is 1
x = 1;
while (x + 1 <= maxX)
{
if (y(x) > y(x-1) and y(x) > y(x+1))
// we found a maximum at x
if (y(x) < y(x-1) and y(x) < y(x+1))
// we found a minimum at x
x = x + 1
}
For 2-point neighborhood maximum condition could be
if (y(x) > y(x-1) and y(x-1) >= y(x-2) and y(x) > y(x+1) and y(x+1) >= y(x+2))
Note >= here. You may use > instead.
Note that above approach won't find maximum in case two consecutive x have the same value y e.g. for y(0) = 0, y(1) = 1, y(2) = 1, y(3) = 0 it won't find maximum neither for x = 1, nor for x = 2.

How do I set LinePlot line thickness and style? (DigitalMicrograph script)

The scripting help documentation of DigitalMicrograph offers an example for setting LinePlot styles with respect of colour and fill (see example script below).
However, the ImageDisplay menu for LinePlots also allows setting line styles (dotted, dashed,...) line thickness and transparency. Can somebody give an example on how to set these values, please?
// create image and image document
ImageDocument imageDoc = CreateImageDocument( "New ImageDocument" )
number width = 256
number height = 5
image img := RealImage("Line Plot Test", 4, width, height )
img = sin( irow + icol/100 )
// add LinePlotImageDisplay to ImageDocument
ImageDisplay imgdsp = imageDoc.ImageDocumentAddImageDisplay( img, 3 )
imgdsp.LinePlotImageDisplaySetContrastLimits( -1.1, 1.1 )
imgdsp.LinePlotImageDisplaySetDoAutoSurvey( 0, 0 )
// draw fill and line for slice 0
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle(0, 3)
// set line color to red
imgdsp.LinePlotImageDisplaySetSliceComponentColor(0, 0, 1, 0, 0)
// set fill color to yellow
imgdsp.LinePlotImageDisplaySetSliceComponentColor(0, 1, 0.9, 0.9, 0)
// draw fill for slice 1 and 2
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle(1, 2)
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle(2, 2)
// draw line for slice 3 and 4
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle(3, 1)
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle(4, 1)
imageDoc.ImageDocumentShow()
The commands you are looking for are:
void LinePlotImageDisplaySetSliceLineThickness( LinePlotImageDisplay lpid, Number slice_id, Number lineThickness )
void LinePlotImageDisplaySetSliceLineStyle( LinePlotImageDisplay lpid, Number slice_id, Number lineStyle )
void LinePlotImageDisplaySetSliceTransparency( LinePlotImageDisplay lpid, Number sliceIndex, Boolean doTransparent, Number transparency )
They are demonstrated in the example below. Note that the visibility of line styles depend on the number of points in a LinePlot. If the LinePlot has more data points than displayed pixels, you may not notice the line style as it is defined 'in between' data points:
// create image and image document
ImageDocument imageDoc = CreateImageDocument( "New ImageDocument" )
number width = 64
number height = 10
image img := RealImage("Line Plot Test", 4, width, height )
img = sin( irow + icol / iwidth * 2 * Pi() ) + ( irow < ( height / 2 ) ? 1.5 : -1.5 )
// add LinePlotImageDisplay to ImageDocument
ImageDisplay imgdsp = imageDoc.ImageDocumentAddImageDisplay( img, 3 )
imgdsp.LinePlotImageDisplaySetContrastLimits( -2.6, 2.6 )
imgdsp.LinePlotImageDisplaySetDoAutoSurvey( 0, 0 )
// Line style demo
for ( number i = 0 ; i < height / 2 ; i++ )
{
number index = i + height / 2
// Set Line - drawing (no fill)
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle( index , 1 )
// Set black line
imgdsp.LinePlotImageDisplaySetSliceComponentColor( index , 0 , 0, 0, 0 )
// Set LineThickness
imgdsp.LinePlotImageDisplaySetSliceLineThickness( index , height / 2 - i + 1 )
// Set LineStyle
imgdsp.LinePlotImageDisplaySetSliceLineStyle( index , i )
}
// Transparecny demo
for ( number i = 0 ; i < height / 2 ; i++ )
{
number index = i
// Set Fill & Line - drawing
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle( index , 1 + 2 )
// Set black fill & red line
imgdsp.LinePlotImageDisplaySetSliceComponentColor( index , 1 , 0 , 0 , 0 )
imgdsp.LinePlotImageDisplaySetSliceComponentColor( index , 0 , 255 , 0 , 0 )
// Set transparency ( 70% transparency = 30% opacity )
imgdsp.LinePlotImageDisplaySetSliceTransparency( index , 1 , 0.7 )
}
imageDoc.ImageDocumentShow()