Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with runPipelineNode then writeImageLocalFile #158

Closed
yh3ds opened this issue Jan 10, 2019 · 5 comments
Closed

Problem with runPipelineNode then writeImageLocalFile #158

yh3ds opened this issue Jan 10, 2019 · 5 comments

Comments

@yh3ds
Copy link

yh3ds commented Jan 10, 2019

Hello,
I try to adapt BinShrink example to write the ShrinkImage on the hard drive (using writeImageLocalFile).

If I just load the image and write it, I don t have any problem.
If I load the image, runPipelineNode with hello.cxx (the code from the sample) and then try to write the outputs on the disk. I have nothing written.... is there a bug or am I doing something wrong ?

Thanks a lot


Here are the sources used


index.js

const path = require('path')
const runPipelineNode = require('itk/runPipelineNode.js')

const readImageLocalFile = require('itk/readImageLocalFile.js')
const writeImageLocalFile = require('itk/writeImageLocalFile.js')

const IOTypes = require('itk/IOTypes.js')

const pipelinePath = path.resolve(__dirname, 'web-build', 'hello' )

const testInputFilePath = path.resolve(__dirname, 'cthead1.png')
const testOutputFilePath = path.resolve(__dirname, 'cthead1Shrink.png')

/* * /
// Working piece of code
readImageLocalFile(testInputFilePath)
.then(function (image) {
const useCompression = false
return writeImageLocalFile(useCompression, image, testOutputFilePath)
})
/* */
// Piece of code not with bug
readImageLocalFile(testInputFilePath)
.then(function (image) {
const args = ['cthead1.png.json', 'cthead1Shrink.png.json', '4']
const desiredOutputs = [
{ path: args[1], type: IOTypes.Image }
]
const inputs = [
{ path: args[0], type: IOTypes.Image, data: image }
]

  return runPipelineNode(pipelinePath, args, desiredOutputs, inputs)
}).then(function ({stdout, stderr, outputs}) {

    const useCompression = false
    return writeImageLocalFile(useCompression, outputs[0].data, testOutputFilePath)
}).then(function () {
    console.log("DEBUG - Script runned - Output written on disk")
})

/* */


hello.cxx

#include

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

#include "itkBinShrinkImageFilter.h"

int main( int argc, char *argv[] ) {

// Test from website
if( argc < 4 )
{
std::cerr << "Usage: " << argv[0] << " " << std::endl;
return EXIT_FAILURE;
}

std::cout << "Inside js coming from cxx" << std::endl;

const char * inputImageFile = argv[1];
const char * outputImageFile = argv[2];
unsigned int shrinkFactor = atoi( argv[3] );

using PixelType = unsigned char;
constexpr unsigned int Dimension = 2;
using ImageType = itk::Image< PixelType, Dimension >;

using ReaderType = itk::ImageFileReader< ImageType >;
auto reader = ReaderType::New();
reader->SetFileName( inputImageFile );

using ShrinkFilterType = itk::BinShrinkImageFilter< ImageType, ImageType >;
auto shrinker = ShrinkFilterType::New();
shrinker->SetInput( reader->GetOutput() );
shrinker->SetShrinkFactors( shrinkFactor );

using WriterType = itk::ImageFileWriter< ImageType >;
auto writer = WriterType::New();
writer->SetInput( shrinker->GetOutput() );
writer->SetFileName( outputImageFile );

try
{
writer->Update();
}
catch( itk::ExceptionObject & error )
{
std::cerr << "Error: " << error << std::endl;
return EXIT_FAILURE;
}

return EXIT_SUCCESS;

}


CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(HelloWorld)

FIND_PACKAGE ( ITK )

IF ( ITK_FOUND )
INCLUDE( ${ITK_USE_FILE} )
ELSE (ITK_FOUND)
MESSAGE (FATAL ERROR
"itk not found. Il est ou?")
ENDIF( ITK_FOUND )

set(io_components ITKImageIO)
if(EMSCRIPTEN)
set(io_components BridgeJavaScript)
endif()
find_package(ITK REQUIRED
COMPONENTS ${io_components}
ITKImageGrid
)
include(${ITK_USE_FILE})

if(EMSCRIPTEN)
include(ITKBridgeJavaScript)
web_add_executable(hello hello.cxx)
web_target_link_libraries(hello ${ITK_LIBRARIES})
else()
add_executable(hello hello.cxx)
target_link_libraries(hello ${ITK_LIBRARIES})
endif()

@thewtex
Copy link
Member

thewtex commented Jan 11, 2019

Hi @yh3ds ,

I think we are running into Node behavior where the process is exiting before the promises have resolved.

@yh3ds
Copy link
Author

yh3ds commented Jan 14, 2019

Hi @thewtex ,
maybe but I m not sure. At least, it looks strange when I write logs to follow the process.
Indeed I get :

DEBUG - Script runned - Before read image
DEBUG - Script runned - Image read, before run pipeline
Inside js coming from cxx - START
Inside js coming from cxx - END
DEBUG - Script runned - Pipeline runned, before write output on disk

Which looks like expected.
Nonetheless, there is one last log missing (I put on when writing output on disk is over. I tested when I just read and write directly and it is printed correctly)

I can imagine two possibilities for the problem :


Question 1

Would it be possible that image coming from run node is corrupted or different than expected ?

Indeed if I log what I m going to write in case of working case (just read / write), I got :

DEBUG - Write output on disk - image : Image {
imageType:
ImageType {
dimension: 2,
componentType: 'uint8_t',
pixelType: 2,
components: 3 },
name: 'Image',
origin: [ 0, 0 ],
spacing: [ 1, 1 ],
direction: Matrix { rows: 2, columns: 2, data: [ 1, 0, 0, 1 ] },
size: [ 256, 256 ],
data:
Uint8Array [
0,
0,
0,
0,
...

But with the 'failing' pipeline, I got :

DEBUG - Write output on disk - outputs[0].data : { imageType:
{ dimension: 2,
componentType: 'uint8_t',
pixelType: 1,
components: 1 },
origin: [ 1.5, 1.5 ],
spacing: [ 4, 4 ],
direction: [ 1, 0, 0, 1 ],
size: [ 64, 64 ],
data: ArrayBuffer { byteLength: 4096 } }

But this second image looks strange isn t it ?
So maybe it is a problem with the cxx ?


Question 2

In the .cxx converted in js, we finish the script with writer->Update(); I guess we don't wait for this Update method to be finished and then we return.
So maybe the problem is just coming from this ?
We need (in a way or another) to force or cxx (converted in js) to wait the end of this Update before exiting ?

Thanks a lot,
Yves

@thewtex
Copy link
Member

thewtex commented Jan 16, 2019

Re: Question 1: that looks OK to me.

Re: Question 2: the executable will run synchronously and it should not return until your .cxx calls return from main.

I recently added a synchronous API for running in Node. Once it has been released, I will ping you so we can see if that fixed your problem.

@thewtex
Copy link
Member

thewtex commented Jan 30, 2019

@yh3ds itk.js 9.2.0 has been released. Could you please try the synchronous API? i.e.

const image = readImageLocalFileSync(testInputFilePath)
const result = runPipelineNodeSync(pipelinePath, args, outputs, inputs) 
[....]

@thewtex
Copy link
Member

thewtex commented Mar 18, 2019

@yh3ds I assume the *Sync functions solved your issue. If there are still problems, please re-open.

@thewtex thewtex closed this as completed Mar 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants