Isis Developer Reference
ProcessByBrick.h
Go to the documentation of this file.
1#ifndef ProcessByBrick_h
2#define ProcessByBrick_h
8/* SPDX-License-Identifier: CC0-1.0 */
9#include <functional>
10#include <QtConcurrentMap>
11#include <QTime>
12
13#include "Brick.h"
14#include "Buffer.h"
15#include "Cube.h"
16#include "Process.h"
17#include "Progress.h"
18
19namespace Isis {
83 class ProcessByBrick : public Process {
84 public:
87
89 virtual ~ProcessByBrick();
90
94
99
101 Cube *SetInputCube(const QString &parameter,
102 int requirements = 0);
103
104 Cube *SetInputCube(const QString &fname,
105 const CubeAttributeInput &att,
106 int requirements = 0);
107
108 virtual void SetBricks(IOCubes cn);
109 void VerifyCubes(IOCubes cn);
110
111 void SetBrickSize(int ns, int nl, int nb);
112
113 void SetInputBrickSize(int ns, int nl, int nb);
114 void SetInputBrickSize(int ns, int nl, int nb, int cube);
115
116 void SetOutputBrickSize(int ns, int nl, int nb);
117 void SetOutputBrickSize(int ns, int nl, int nb, int cube);
118
119 // Overload the SetOutputCube() method to allow the user to pass in the
120 // file name and attributes without the lines and samples.
121 // Any other calls to this method will use the prototypes found in the
122 //process class due to the using statement below.
124 virtual Cube *SetOutputCube(const QString &fname,
125 const CubeAttributeOutput &att);
126
129
130 void SetOutputRequirements(int outputRequirements);
131 void SetWrap(bool wrap);
132 bool Wraps();
133
134 using Isis::Process::StartProcess; // make parents virtual function visable
135 virtual void StartProcess(void funct(Buffer &in));
136 virtual void StartProcess(std::function<void(Buffer &in)> funct );
137 virtual void StartProcess(void funct(Buffer &in, Buffer &out));
138 virtual void StartProcess(std::function<void(Buffer &in, Buffer &out)> funct);
139 virtual void StartProcess(void funct(std::vector<Buffer *> &in,
140 std::vector<Buffer *> &out));
141 virtual void StartProcess(std::function<void(std::vector<Buffer *> &in,
142 std::vector<Buffer *> &out)> funct);
143 void EndProcess();// Depricated. Please use Finalize
144 void Finalize();
145
146
167 template <typename Functor> void ProcessCubeInPlace(
168 const Functor & functor, bool threaded = true) {
169 Cube *cube = NULL;
170 Brick *brick = NULL;
171
172 bool haveInput = PrepProcessCubeInPlace(&cube, &brick);
173 bool writeOutput = (!haveInput) || (cube->isReadWrite());
174
175 ProcessCubeInPlaceFunctor<Functor> wrapperFunctor(
176 cube, brick, haveInput, writeOutput, functor);
177
178 RunProcess(wrapperFunctor, brick->Bricks(), threaded);
179
180 delete brick;
181 }
182
183
204 template <typename Functor> void ProcessCube(const Functor & functor,
205 bool threaded = true) {
206 Brick *inputCubeData = NULL;
207 Brick *outputCubeData = NULL;
208
209 int numBricks = PrepProcessCube(&inputCubeData, &outputCubeData);
210
211 ProcessCubeFunctor<Functor> wrapperFunctor(InputCubes[0], inputCubeData,
212 OutputCubes[0], outputCubeData, functor);
213
214 RunProcess(wrapperFunctor, numBricks, threaded);
215
216 delete inputCubeData;
217 delete outputCubeData;
218 }
219
220
243 template <typename Functor> void ProcessCubes(const Functor & functor,
244 bool threaded = true) {
245 std::vector<Brick *> inputCubeData;
246 std::vector<Brick *> outputCubeData;
247
248 std::vector<Buffer *> inputCubeDataParents;
249 std::vector<Buffer *> outputCubeDataParents;
250
251 int numBricks = PrepProcessCubes(
252 inputCubeDataParents, outputCubeDataParents,
253 inputCubeData, outputCubeData);
254
255 ProcessCubesFunctor<Functor> wrapperFunctor(InputCubes, inputCubeData,
256 OutputCubes, outputCubeData, Wraps(), functor);
257
258 RunProcess(wrapperFunctor, numBricks, threaded);
259
260 for(unsigned int i = 0; i < inputCubeData.size(); i++) {
261 delete inputCubeData[i];
262 }
263
264 for(unsigned int i = 0; i < outputCubeData.size(); i++) {
265 delete outputCubeData[i];
266 }
267 }
268
269
270 private:
283 template <typename Functor>
284 void RunProcess(const Functor &wrapperFunctor,
285 int numSteps, bool threaded) {
286 ProcessIterator begin(0);
287 ProcessIterator end(numSteps);
288
289 p_progress->SetMaximumSteps(numSteps);
291
292 int threadCount = QThreadPool::globalInstance()->maxThreadCount();
293 if (threaded && threadCount > 1) {
294 QFuture<void> result = QtConcurrent::mapped(begin, end,
295 wrapperFunctor);
296 BlockingReportProgress(result);
297 }
298 else {
299 while (begin != end) {
300 wrapperFunctor(*begin);
301 ++begin;
303 }
304 }
305 }
306
307
322 template <typename T>
323 class ProcessCubeInPlaceFunctor :
324 public std::function<void*(int)> {
325 public:
341 ProcessCubeInPlaceFunctor(Cube *cube,
342 const Brick *templateBrick,
343 bool readInput, bool writeOutput,
344 const T &processingFunctor) :
345 m_cube(cube),
346 m_templateBrick(templateBrick),
347 m_readInput(readInput),
348 m_writeOutput(writeOutput),
349 m_processingFunctor(processingFunctor) {
350 }
351
352
358 ProcessCubeInPlaceFunctor(const ProcessCubeInPlaceFunctor &other) :
359 m_cube(other.m_cube),
360 m_templateBrick(other.m_templateBrick),
361 m_readInput(other.m_readInput),
362 m_writeOutput(other.m_writeOutput),
363 m_processingFunctor(other.m_processingFunctor) {
364 }
365
366
370 virtual ~ProcessCubeInPlaceFunctor() {
371 m_cube = NULL;
372 m_templateBrick = NULL;
373 }
374
375
382 void *operator()(const int &brickPosition) const {
383 Brick cubeData(*m_templateBrick);
384 cubeData.setpos(brickPosition);
385
386 if (m_readInput)
387 m_cube->read(cubeData);
388
389 m_processingFunctor(cubeData);
390
391 if (m_writeOutput)
392 m_cube->write(cubeData);
393
394 return NULL;
395 }
396
397
405 ProcessCubeInPlaceFunctor &operator=(
406 const ProcessCubeInPlaceFunctor &rhs) {
407 m_cube = rhs.m_cube;
408 m_templateBrick = rhs.m_templateBrick;
409
410 m_readInput = rhs.m_readInput;
411 m_writeOutput = rhs.m_writeOutput;
412
413 m_processingFunctor = rhs.m_processingFunctor;
414
415 return *this;
416 }
417
418 private:
420 Cube *m_cube;
422 const Brick *m_templateBrick;
424 bool m_readInput;
426 bool m_writeOutput;
427
429 const T &m_processingFunctor;
430 };
431
432
446 template <typename T>
447 class ProcessCubeFunctor :
448 public std::function<void *(const int &)> {
449 public:
465 ProcessCubeFunctor(Cube *inputCube,
466 const Brick *inputTemplateBrick,
467 Cube *outputCube,
468 const Brick *outputTemplateBrick,
469 const T &processingFunctor) :
470 m_inputCube(inputCube),
471 m_inputTemplateBrick(inputTemplateBrick),
472 m_outputCube(outputCube),
473 m_outputTemplateBrick(outputTemplateBrick),
474 m_processingFunctor(processingFunctor) {
475 }
476
477
483 ProcessCubeFunctor(const ProcessCubeFunctor &other) :
484 m_inputCube(other.m_inputCube),
485 m_inputTemplateBrick(other.m_inputTemplateBrick),
486 m_outputCube(other.m_outputCube),
487 m_outputTemplateBrick(other.m_outputTemplateBrick),
488 m_processingFunctor(other.m_processingFunctor) {
489 }
490
491
495 virtual ~ProcessCubeFunctor() {
496 m_inputTemplateBrick = NULL;
497 m_outputTemplateBrick = NULL;
498 }
499
500
507 void *operator()(const int &brickPosition) const {
508 Brick inputCubeData(*m_inputTemplateBrick);
509 Brick outputCubeData(*m_outputTemplateBrick);
510
511 inputCubeData.setpos(brickPosition);
512 outputCubeData.setpos(brickPosition);
513
514 m_inputCube->read(inputCubeData);
515
516 m_processingFunctor(inputCubeData, outputCubeData);
517
518 m_outputCube->write(outputCubeData);
519
520 return NULL;
521 }
522
523
531 ProcessCubeFunctor &operator=(const ProcessCubeFunctor &rhs) {
532 m_inputCube = rhs.m_inputCube;
533 m_inputTemplateBrick = rhs.m_inputTemplateBrick;
534
535 m_outputCube = rhs.m_outputCube;
536 m_outputTemplateBrick = rhs.m_outputTemplateBrick;
537
538 m_processingFunctor = rhs.m_processingFunctor;
539
540 return *this;
541 }
542
543 private:
545 Cube *m_inputCube;
547 const Brick *m_inputTemplateBrick;
548
550 Cube *m_outputCube;
552 const Brick *m_outputTemplateBrick;
553
555 const T &m_processingFunctor;
556 };
557
558
573 template <typename T>
574 class ProcessCubesFunctor :
575 public std::function<void *(const int &)> {
576 public:
596 ProcessCubesFunctor(std::vector<Cube *> &inputCubes,
597 std::vector<Brick *> &inputTemplateBricks,
598 std::vector<Cube *> &outputCubes,
599 std::vector<Brick *> &outputTemplateBricks,
600 bool wraps,
601 const T &processingFunctor) :
602 m_inputCubes(inputCubes),
603 m_inputTemplateBricks(inputTemplateBricks),
604 m_outputCubes(outputCubes),
605 m_outputTemplateBricks(outputTemplateBricks),
606 m_wraps(wraps),
607 m_processingFunctor(processingFunctor) {
608 }
609
610
616 ProcessCubesFunctor(const ProcessCubesFunctor &other) :
617 m_inputCubes(other.m_inputCubes),
618 m_inputTemplateBricks(other.m_inputTemplateBricks),
619 m_outputCubes(other.m_outputCubes),
620 m_outputTemplateBricks(other.m_outputTemplateBricks),
621 m_wraps(other.m_wraps),
622 m_processingFunctor(other.m_processingFunctor) {
623 }
624
625
629 virtual ~ProcessCubesFunctor() {
630 }
631
632
639 void *operator()(const int &brickPosition) const {
640 QPair< std::vector<Buffer *>, std::vector<Buffer *> > functorBricks;
641
642 for (int i = 0; i < (int)m_inputTemplateBricks.size(); i++) {
643 Brick *inputBrick = new Brick(*m_inputTemplateBricks[i]);
644 functorBricks.first.push_back(inputBrick);
645
646 if (m_wraps) {
647 inputBrick->setpos(brickPosition % inputBrick->Bricks());
648 }
649 else {
650 inputBrick->setpos(brickPosition);
651 }
652
653 if (i != 0 &&
654 functorBricks.first.size() &&
655 inputBrick->Band() != functorBricks.first[0]->Band() &&
656 m_inputCubes[i]->bandCount() != 1) {
657 inputBrick->SetBaseBand(functorBricks.first[0]->Band());
658 }
659
660 m_inputCubes[i]->read(*inputBrick);
661 }
662
663 for (int i = 0; i < (int)m_outputTemplateBricks.size(); i++) {
664 Brick *outputBrick = new Brick(*m_outputTemplateBricks[i]);
665 functorBricks.second.push_back(outputBrick);
666 outputBrick->setpos(brickPosition);
667 }
668
669 // Pass them to the application function
670 m_processingFunctor(functorBricks.first, functorBricks.second);
671
672 // And copy them into the output cubes
673 for (int i = 0; i < (int)functorBricks.second.size(); i++) {
674 m_outputCubes[i]->write(*functorBricks.second[i]);
675 delete functorBricks.second[i];
676 }
677
678 for (int i = 0; i < (int)functorBricks.first.size(); i++) {
679 delete functorBricks.first[i];
680 }
681
682 return NULL;
683 }
684
685
693 ProcessCubesFunctor &operator=(const ProcessCubesFunctor &rhs) {
694 m_inputCubes = rhs.m_inputCubes;
695 m_inputTemplateBricks = rhs.m_inputTemplateBricks;
696
697 m_outputCubes = rhs.m_outputCubes;
698 m_outputTemplateBricks = rhs.m_outputTemplateBricks;
699
700 m_wraps = rhs.m_wraps;
701
702 m_processingFunctor = rhs.m_processingFunctor;
703
704 return *this;
705 }
706
707 private:
709 std::vector<Cube *> m_inputCubes;
714 std::vector<Brick *> &m_inputTemplateBricks;
715
717 std::vector<Cube *> m_outputCubes;
722 std::vector<Brick *> &m_outputTemplateBricks;
723
725 bool m_wraps;
726
728 const T &m_processingFunctor;
729 };
730
731
732 void BlockingReportProgress(QFuture<void> &future);
733 std::vector<int> CalculateMaxDimensions(std::vector<Cube *> cubes) const;
734 bool PrepProcessCubeInPlace(Cube **cube, Brick **bricks);
735 int PrepProcessCube(Brick **ibrick, Brick **obrick);
736 int PrepProcessCubes(std::vector<Buffer *> & ibufs,
737 std::vector<Buffer *> & obufs,
738 std::vector<Brick *> & imgrs,
739 std::vector<Brick *> & omgrs);
740
741
751 class ProcessIterator {
752 public:
753 ProcessIterator(int position);
754 ProcessIterator(const ProcessIterator &other);
755 virtual ~ProcessIterator();
756
757 using value_type = int;
758 using iterator_category = std::forward_iterator_tag;
759 using difference_type = std::ptrdiff_t;
760 using pointer = int*;
761 using reference = int&;
762
763 ProcessIterator &operator++();
764
771 bool operator==(const ProcessIterator &rhs) {
772 return (m_currentPosition == rhs.m_currentPosition);
773 }
774
781 bool operator!=(const ProcessIterator &rhs) {
782 return !(*this == rhs);
783 }
784
785
791 void swap(ProcessIterator &other) {
792 std::swap(m_currentPosition, other.m_currentPosition);
793 }
794
795
802 ProcessIterator &operator=(const ProcessIterator &rhs) {
803 ProcessIterator copy(rhs);
804 swap(copy);
805 return *this;
806 }
807
808
813 int operator*() const {
814 return m_currentPosition;
815 }
816
817 private:
819 int m_currentPosition;
820 };
821
822 private:
823 bool p_reverse;
826 bool p_wrapOption;
827 bool p_inputBrickSizeSet;
829 bool p_outputBrickSizeSet;
832 int p_outputRequirements;
833
834
835 std::vector<int> p_inputBrickSamples;
837 std::vector<int> p_inputBrickLines;
839 std::vector<int> p_inputBrickBands;
841 std::vector<int> p_outputBrickSamples;
843 std::vector<int> p_outputBrickLines;
845 std::vector<int> p_outputBrickBands;
851 };
852
853};
854
855#endif
Buffer for containing a three dimensional section of an image.
Definition Brick.h:45
Buffer for reading and writing cube data.
Definition Buffer.h:53
Manipulate and parse attributes of input cube filenames.
Definition CubeAttribute.h:381
Manipulate and parse attributes of output cube filenames.
Definition CubeAttribute.h:473
IO Handler for Isis Cubes.
Definition Cube.h:168
void read(Blob &blob, const std::vector< PvlKeyword > keywords=std::vector< PvlKeyword >()) const
This method will read data from the specified Blob object.
Definition Cube.cpp:814
void write(Blob &blob, bool overwrite=true)
This method will write a blob of data (e.g.
Definition Cube.cpp:978
bool isReadWrite() const
Test if the opened cube is read-write, that is read and write operations should succeed if this is tr...
Definition Cube.cpp:231
Process cubes by brick.
Definition ProcessByBrick.h:83
void SetOutputRequirements(int outputRequirements)
Definition ProcessByBrick.cpp:95
void SetProcessingDirection(ProcessingDirection direction)
Set the direction the data will be read, either all lines in a single band proceeding to the next ban...
Definition ProcessByBrick.cpp:380
void Finalize()
Cleans up by closing cubes and freeing memory.
Definition ProcessByBrick.cpp:749
ProcessingDirection
Definition ProcessByBrick.h:95
@ LinesFirst
Definition ProcessByBrick.h:96
@ BandsFirst
Definition ProcessByBrick.h:97
void ProcessCubeInPlace(const Functor &functor, bool threaded=true)
Operate over a single cube (either input or output).
Definition ProcessByBrick.h:167
ProcessByBrick()
Constructs a ProcessByBrick object.
Definition ProcessByBrick.cpp:16
void ProcessCubes(const Functor &functor, bool threaded=true)
Operate over an arbitrary number of input cubes given an arbitrary number of output cubes.
Definition ProcessByBrick.h:243
void SetOutputBrickSize(int ns, int nl, int nb)
Sets the size of all output bricks.
Definition ProcessByBrick.cpp:300
void VerifyCubes(IOCubes cn)
Verifies the dimensions of the input/output cubes.
Definition ProcessByBrick.cpp:120
void SetInputBrickSize(int ns, int nl, int nb)
Sets the size of all input bricks.
Definition ProcessByBrick.cpp:241
virtual void StartProcess(void funct(Buffer &in))
Starts the systematic processing of the input cube by moving an arbitrarily-shaped brick through the ...
Definition ProcessByBrick.cpp:436
Cube * SetInputCube(const QString &parameter, int requirements=0)
Opens an input cube specified by the user and verifies requirements are met.
Definition ProcessByBrick.cpp:58
void ProcessCube(const Functor &functor, bool threaded=true)
Operate over a single input cube creating a separate output cube.
Definition ProcessByBrick.h:204
void SetBrickSize(int ns, int nl, int nb)
Sets the input and output bricks sizes to the given number of samples, lines, and bands.
Definition ProcessByBrick.cpp:225
void SetWrap(bool wrap)
This wrapping option only applys when there are two or more input cubes.
Definition ProcessByBrick.cpp:409
IOCubes
Definition ProcessByBrick.h:91
@ InputOutput
Definition ProcessByBrick.h:92
@ InputOutputList
Definition ProcessByBrick.h:93
@ InPlace
Definition ProcessByBrick.h:91
bool Wraps()
Returns true if the wrapping option is enabled.
Definition ProcessByBrick.cpp:419
virtual ~ProcessByBrick()
Destroys the ProcessByBrick object.
Definition ProcessByBrick.cpp:35
virtual void SetBricks(IOCubes cn)
Definition ProcessByBrick.cpp:102
void EndProcess()
End the processing sequence and cleans up by closing cubes, freeing memory, etc.
Definition ProcessByBrick.cpp:739
virtual Cube * SetOutputCube(const QString &fname, const CubeAttributeOutput &att)
Create the output file.
Definition ProcessByBrick.cpp:364
ProcessingDirection GetProcessingDirection()
Returns the direction the data will be read, either all lines in a single band proceeding to the next...
Definition ProcessByBrick.cpp:393
Base class for all cube processing derivatives.
Definition Process.h:143
virtual void StartProcess(void funct())
In the base class, this method will invoked a user-specified function exactly one time.
Definition Process.h:213
std::vector< Isis::Cube * > InputCubes
A vector of pointers to opened Cube objects.
Definition Process.h:185
Isis::Progress * p_progress
Pointer to a Progress object.
Definition Process.h:145
virtual Isis::Cube * SetOutputCube(const QString &parameter)
Allocates a user-specified output cube whose size matches the first input cube.
Definition Process.cpp:163
std::vector< Isis::Cube * > OutputCubes
A vector of pointers to allocated Cube objects.
Definition Process.h:191
virtual Isis::Cube * SetInputCube(const QString &parameter, const int requirements=0)
Opens an input cube specified by the user and verifies requirements are met.
Definition Process.cpp:139
void SetMaximumSteps(const int steps)
This sets the maximum number of steps in the process.
Definition Progress.cpp:85
void CheckStatus()
Checks and updates the status.
Definition Progress.cpp:105
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16