<div dir="ltr">Hi Brad,<div><br></div><div>Thanks for the help. Sorry I left so much out of the code, I thought I was already pasting too much for the mailing list.</div><div><br></div><div style>As for the comments. I have an update prior to that code to ensure the output information is available. The reason I had the paste filter declared outside the loop as I was attempting to use the output of the last iteration as input for the remainder of the pipeline. e.g.</div>
<div style><br></div><div style>Filter f</div><div style><br></div><div style>for i->n</div><div style>f = new</div><div style>f->update</div><div style>end for</div><div style><br></div><div style>Filter g</div><div style>
g->SetInput(f->GetOutput())</div><div style><br></div><div style>I've modified this now to be:</div><div style><br></div><div style>for i->N</div><div style><br></div><div style>Filter f = new</div><div style>
f->Destination(sortedImage)</div><div style>f->Update()</div><div style>sortedImage=f->GetOutput()</div><div style><br></div><div style>end for</div><div style><br></div><div style>Filter g</div><div style>g->SetInput(sortedImage);</div>
<div style><br></div><div style>This seems to work fine as the final image is as expected. I think the reason I was getting a black image, rather than a zero image, was because only the final iteration of the loop was doing anything (instead of the first as I presumed). The filter was never being executed in the earlier iterations.</div>
<div style><br></div><div style>So now I have a solution that works, but given I have Ns paste filters running, it is less than efficient. Do you have any advice on how to perform this operation in a less inefficient way? I feel the PasteFilter is probably not the best solution for mapping one image to another. The ResampleFilter comes to mind, but I'm unsure how to construct a transform that is a function rather than a constant shift as in the translation examples.</div>
<div style><br></div><div style>The pipeline is used only once. Prior to this section many filters and transforms are executed in a very straightforward way, no loops or reuse. Just about 8 filters set input to output in a standard pipeline. I would have preferred to take the pixel buffer and do this part of the problem "manually" but I'm trying to stay within the ITK paradigm.</div>
<div style><br></div><div style>Cheers,</div><div style>Phil</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On 8 April 2013 23:42, Bradley Lowekamp <span dir="ltr"><<a href="mailto:blowekamp@mail.nih.gov" target="_blank">blowekamp@mail.nih.gov</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">Hello Phillip,<div><br></div><div>You didn't include where you updates were so I'll mention what I see as common problems</div>
<div><br><div><div class="im"><div>On Apr 7, 2013, at 6:24 PM, Phillip Ward <<a href="mailto:pgwar1@student.monash.edu" target="_blank">pgwar1@student.monash.edu</a>> wrote:</div><div><br></div></div><div class="im">
<blockquote type="cite"><div dir="ltr"><div><div> // Sort image slices</div><div> // Allocate space for sorted image</div><div> ImageType::Pointer sortedImage = ImageType::New();</div>
<div>
sortedImage->SetRegions(accumulateFilter->GetOutput()->GetLargestPossibleRegion());</div></div></div></blockquote><div><br></div></div><div>It is important that accumulateFilter has been updated before this point so that is has the correct Image output information such as size and spacing etc... Technically just accumulateFilter->UpdateOutputInformation() is needed, but executing the primary generate data method with the normal "Update" should be ok too.</div>
<div class="im"><div><br></div> <br><blockquote type="cite"><div dir="ltr"><div><div> sortedImage->Allocate();</div><div><br></div><div> // Size of slices to be sorted</div>
<div> ImageType::SizeType sourceSize;</div><div> sourceSize[0] = Kx;</div><div> sourceSize[1] = Ky;</div><div> sourceSize[2] = 1;</div><div> sourceSize[3] = 1;</div>
<div><br></div><div> PasteFilterType::Pointer pasteFilter = PasteFilterType::New ();</div><div> ImageType::RegionType sourceRegion;<br></div></div></div></blockquote><div><br></div></div><div>
So you are creating a paste filter outside the loop here...</div><div class="im"><br><blockquote type="cite"><div dir="ltr"><div><div><br></div><div> for (int i = 0; i < Ns; ++i)</div>
<div> {</div><div> ImageType::IndexType sourceIndex;</div><div> sourceIndex[0] = 0;</div><div> sourceIndex[1] = 0;</div><div> sourceIndex[2] = i;</div>
<div> sourceIndex[3] = 0;</div><div><br></div><div> ImageType::IndexType destinationIndex; </div><div> if (i%2 == 0) {</div><div> destinationIndex[0] = 0;</div>
<div> destinationIndex[1] = 0;</div><div> destinationIndex[2] = i/2; </div><div> destinationIndex[3] = 0;</div><div> } else {</div><div> destinationIndex[0] = 0;</div>
<div> destinationIndex[1] = 0;</div><div> destinationIndex[2] = i/2 + Ns/2 + Ns%2;</div><div> destinationIndex[3] = 0;</div><div> }</div><div>
<br></div><div> sourceRegion.SetSize(sourceSize);</div><div> sourceRegion.SetIndex(sourceIndex);</div></div></div></blockquote><blockquote type="cite"><div dir="ltr"><div><div><br></div>
<div> // Paste even slices before odd slices</div>
<div> pasteFilter = PasteFilterType::New ();</div></div></div></blockquote><div><br></div></div><div>And another here, into the same variable.. This will reduce the reference count of the prior filter to zero, and it will get deleted. So the new paste filter has parent filter, its kind of orphaned.</div>
<div class="im"><br><blockquote type="cite"><div dir="ltr"><div><div> pasteFilter->SetSourceImage(accumulateFilter->GetOutput());</div><div> pasteFilter->SetDestinationImage(sortedImage);</div>
<div> pasteFilter->SetSourceRegion(sourceRegion);</div><div> pasteFilter->SetDestinationIndex(destinationIndex);</div><div><br></div><div> sortedImage = pasteFilter->GetOutput();</div>
</div></div></blockquote><div><br></div></div><div>And there is no update here... and you take you un-updated output and place it back into the input... So there is no way for image to propagate down the pipeline because filters in the pipeline are being disconnected. So based on this I'd expect to see a zero sized image as the output for this pipeline. Not a "black" image...</div>
<div><br></div><div>Also please keep in mind that with you appear to be trying to run Ns PasteFilters, each one create a new copy for the output and copies it to the output. This poses a significant amount of waisted computation, and if you did keep you each paste filter you'd have over Ns images in memory.</div>
<div><br></div><div>I hesitate to give recommendations on how to improve your efficiency with the trouble you have already had and without knowing the goals of you filter i.e. memory efficiency, time efficiency, partial updating of parameters, or streaming..</div>
<div><br></div><div>Hoped this helped,</div><div>Brad</div><div><div class="h5"><br><blockquote type="cite"><div dir="ltr"><div>
<div> }</div><div><br></div><div>Cheers,</div><div>Phil</div><div><br></div></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On 8 April 2013 04:43, Bradley Lowekamp <span dir="ltr"><<a href="mailto:blowekamp@mail.nih.gov" target="_blank">blowekamp@mail.nih.gov</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello Phil,<br>
<br>
It this is the try of problem that SimpleITK excels out. A lot of the time I like to prototype in SimpleITK, then implement it as an ITK pipeline once I know how what filters I need, what parameters I need, how I want the pipeline to flow for efficiency.<br>
<br>
As it sound like you have been struggling for a while with a variety of some of ITK pipeline and other complication, I'd like to suggest you play with he parameters of the filters you are using in a SimpleITK IPython environment, then implement it in the ITK pipeline after you know what the filters should do. So that it'd separate the filter issues from the pipeline issues.<br>
<br>
There are quite a number of ways you could be trying to setup your pipeline, and it's not clear what your pipeline goals are. You also did not provide code, so I really can't give much of a suggestion<br>
<br>
Here is a quick solution in SimpleITK Python:<br>
<br>
import SimpleITK as sitk<br>
img = sitk.ReadImage( "myfile.mha")<br>
Nz = img.GetSize()[2]<br>
limg = [ img[:,:,z//2] if z%2 else img[:,:,Nz//2+z/2] for z in range(0,Nz) ]<br>
rimg = sitk.JoinSeries( limg, img.GetSpacing()[2] )<br>
<br>
Hopefully, that 4th statement isn't to much pythonic short hand. It uses list comprehension combined with sliced based indexing to for a list of 2D z-slices that are re-ordered as you specified.<br>
<br>
The statement "img[:,:,n]" say ":"- all in x, ":"-all in y, and just the "n-th" slice. Internally it's implemented with an ExtractImageFilter to extract a 2D slice from a 3D image.<br>
<br>
Then the JoinSeriesImageFilter, just takes that re-oreded lists of slices an makes a 3D image from it. And the spacing from the old image is used again.<br>
<br>