w4m
w4m

Reputation: 145

How to reshape the dimension of data cube in DM with script

I have an image with dimensions 1024*1024 stored in a HDF5 file, which is treated as a data cube of slice thickness 1, (so that stored dimension is 1024*1024*1) . I used the Niermann HDF5 plug-in (https://github.com/niermann/gms_plugin_hdf5) to import the data. After importing, the data cube became 1*1024*1024, and displayed as 1 pixel wide, 1024 pixels hight and 1024 slices images.

Before considering re-implement the plug-in, I'd like to ask, is there any way to "reshape" the data (like in "Numpy.reshape"), so that the dimensions can be properly treated?

Thanks!

Upvotes: 0

Views: 241

Answers (3)

BmyGuest
BmyGuest

Reputation: 2949

If you don't like icol, irow and these expressions, another elegant solution is to just use the streaming object.

image ReShape3D( image input, number sx, number sy, number sz )
{
    // Perform testing
    number nPix=1
    for ( number d=0; d<input.ImageGetNumDimensions(); d++ )
        nPix *= input.ImageGetDimensionsize(d)

    if ( sx*sy*sz < nPix ) Throw( "Input image larger than provided shape." )
    if ( sx*sy*sz > nPix ) Throw( "Input image smaller than provided shape." )

    image reShaped := input.Imageclone()
    reShaped.ImageResize(3,sx,sy,sz)
    object dStream = NewStreamFromBuffer(0)
    ImageWriteImageDataToStream(input,dStream,0)
    dStream.StreamSetPos(0,0)
    ImageReadImageDataFromStream(reShaped,dStream,0)
    return reshaped
}

Image before := RealImage("Before",4,10,20,30)
before = random()
Image after := ReShape3D( before,20,10,30 )
before.ShowImage()
after.ShowImage()

Upvotes: 0

BmyGuest
BmyGuest

Reputation: 2949

If your input/output array sizes do not match in dimension (such that slice would not work), then you can also 'stream' the data into and out of 1D using the following:

number sx = 4   
number sy = 5   
number sz = 2   

image oneLine := RealImage( "1D",4, sx*sy*sz )
oneLine = icol
oneLine.ShowImage()

image reShape1Dto3D := RealImage( "1D->3D", 4, sx, sy, sz )
reShape1Dto3D = oneLine[icol + iwidth*irow + iwidth*iheight*iplane, 0 ]
reShape1Dto3D.ShowImage()

image reShape3Dto1D := RealImage( "3D->1D", 4, sx*sy*sz )
reShape3Dto1D[icol + iwidth*irow + iwidth*iheight*iplane, 0 ] = reShape1Dto3D
reShape3Dto1D.ShowImage()

The trick here is, that you can address a single value in an image expression using square-brackets. In a 3D image by [X,Y,Z], in a 2D image by [X,Y], and in a 1D images as [X,0]. [*]

The internal variables icol, irow, iplane are replaced by X,Y,Z coordinate of the evaluated expression, whereas iwidth, iheight and idepth are replaced by the dimension sizes of the evaluated expression.

What is the evaluated expression's size? It becomes defined by the only image of "known size" in the line - either left or right side, so that

reShape1Dto3D = oneLine[ icol + iwidth*irow + iwidth*iheight*iplane, 0 ]

becomes a loop over X/Y/Z of all pixels of reShape1Dto3D an the lefthand side of the expression. For each triplet (X/Y/Z) the value is taken from the computed position of oneLine.

Exactly the same is used in

reShape3Dto1D[ icol + iwidth*irow + iwidth*iheight*iplane, 0 ] = reShape1Dto3D

but here the loop is again over the size of reShape1Dto3D, because that is the image of "known size" in the line, even if it is on the righthand side.

* Higher dimensionality is not supported in this way, as [T,L,B,R] is already used for sub-areas.

Upvotes: 0

w4m
w4m

Reputation: 145

After few more trial with the examples in "DM scripting handbook", a method is figured out:

image out = in.slice2(0,0,0, 1,1024,1, 2,1024,1)

that is, the output 2d image in the x-y take the projection of y-z plane of the input image using Slice2() command.

Upvotes: 0

Related Questions