3 #include "StorageController.h"
4 #include "BaseController_p.h"
7 #include "helpers/SyncQueues.h"
8 #include "parameters/Scope.h"
10 #include "helpers/ScopeMultiImage.h"
11 #include "helpers/ScopeMultiImageResonanceSW.h"
12 #include "helpers/hresult_exception.h"
13 #include "helpers/ScopeMultiImageEncoder.h"
14 #include "helpers/ScopeException.h"
15 #include "ScopeLogger.h"
31 std::array<std::vector<std::wstring>, SCOPE_NAREAS>
filenames;
34 std::array<std::unique_ptr<ScopeMultiImageEncoder>, SCOPE_NAREAS>
encoders;
48 DBOUT(L
"StorageController::Impl::Run beginning\n");
49 ControllerReturnStatus returnstatus(ControllerReturnStatus::none);
50 uint32_t framearea = 0;
51 std::wstring foldername(L
"");
52 std::array<ScopeMultiImagePtr, SCOPE_NAREAS> current_frames;
54 std::array<uint32_t, SCOPE_NAREAS> requested_frames;
56 std::generate(std::begin(requested_frames), std::end(requested_frames),
60 && ( (requested_mode == DaqModeHelper::nframes)
77 bool reqEqual, framecountEqual;
78 std::array<uint32_t, SCOPE_NAREAS> totalframecount;
79 totalframecount.assign(0);
83 while ( !sc->
IsSet() ) {
88 if ( msg.tag == ScopeMessageTag::abort ) {
89 returnstatus = ControllerReturnStatus::stopped;
92 DBOUT(L
"StorageController::impl::Run dequeued\n");
94 framearea = msg.cargo->Area();
95 current_frames[framearea] = msg.cargo;
98 assert(
parameters.
areas[framearea]->daq.inputs->channels() == current_frames[framearea]->Channels());
101 encoders[framearea]->NewFrame();
103 encoders[framearea]->WriteFrame(current_frames[framearea]);
106 framecountEqual =
false;
107 const uint32_t maxframes = 3000000000 / ( current_frames[framearea]->Linewidth()*current_frames[framearea]->Lines()*16/8 );
109 for ( uint32_t i = 0; i < SCOPE_NAREAS; i++ ){
110 reqEqual = reqEqual || ( requested_frames.at(i) == encoders.at(i)->Framecount() + totalframecount.at(i) );
111 framecountEqual = framecountEqual || ( encoders.at(i)->Framecount() == maxframes );
115 if ( (requested_mode == DaqModeHelper::nframes) && reqEqual ) {
118 returnstatus = ControllerReturnStatus::finished;
119 DBOUT(L
"StorageController::Impl::Run - all requested frames from all areas saved\n");
123 if ( framecountEqual ) {
124 for ( uint32_t i = 0; i < SCOPE_NAREAS; i++ ) {
125 totalframecount.at(i)+= encoders.at(i)->Framecount();
128 for (
auto& e : encoders )
142 for (
auto& e : encoders )
150 returnstatus = (ControllerReturnStatus)(returnstatus || ControllerReturnStatus::stopped);
152 ATLTRACE(L
"StorageController::Impl::Run end\n");
159 std::wstring runmode(L
"");
161 case RunStateHelper::RunningContinuous:
164 case RunStateHelper::RunningSingle:
165 runmode = L
"_Single";
167 case RunStateHelper::RunningStack:
170 case RunStateHelper::RunningTimeseries:
171 runmode = L
"_Timeseries";
175 std::wstringstream foldername;
178 std::wstring msg = L
"Saving into " + foldername.str();
179 scope_logger.
Log(msg, log_info);
182 if ( SHCreateDirectoryEx(NULL, foldername.str().c_str(), NULL) == ERROR_SUCCESS )
183 return foldername.str();
192 for ( uint32_t a = 0 ; a < SCOPE_NAREAS ; a++ ) {
197 for ( uint32_t c = 0 ; c <
parameters.
areas[a]->daq.inputs->channels() ; c++ ) {
198 std::wstringstream stream;
199 stream << _foldername <<
parameters.
storage.
basename() << L
"_A" << a << L
"_Ch" << c << L
"_ " << std::setfill(L
'0') << std::setw(4) << runcounter << L
".tif";
200 filenames[a][c] = stream.str();
203 encoders[a]->Initialize(filenames[a]);
211 , input_queue(_iqueue)
235 PROCESS_INFORMATION pi;
237 ZeroMemory( &si,
sizeof(si) );
239 ZeroMemory( &pi,
sizeof(pi) );
241 GetCurrentDirectory(255, buff);
244 std::wstringstream cmdbase;
245 cmdbase << L
"-delete_original -overwrite_original_in_place -ResolutionUnit=None -Software=\"Proudly recorded with Scope\" ";
247 case RunStateHelper::RunningStack:
248 cmdbase << L
"-ImageDescription=\"ImageJ=1.47m\nunit=um\nspacing=" <<
parameters.
stack.
spacing() << L
"\" ";
250 case RunStateHelper::RunningTimeseries:
253 cmdbase << L
"-ImageDescription=\"ImageJ=1.47m\nunit=um\" ";
257 for ( uint32_t a = 0 ; a < SCOPE_NAREAS ; a++ ) {
258 std::wstringstream cmd;
259 cmd << cmdbase.str();
270 for ( uint32_t c = 0 ; c <
parameters.
areas[a]->daq.inputs->channels() ; c++ )
271 cmd << L
"\"" << filenames[a][c] << L
"\" ";
274 DBOUT(L
"Cmd: " << cmd.str());
275 std::wstring cmdstr(cmd.str());
276 std::vector<wchar_t> wincmd(cmdstr.begin(), cmdstr.end());
277 if ( 0 == CreateProcess(L
"tools/exiftool.exe", wincmd.data(), NULL, NULL, FALSE, BELOW_NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, NULL, &si, &pi) ) {
278 std::wstringstream errstr;
279 errstr << L
"exiftool.exe did not start with error " << GetLastError();
280 scope_logger.
Log(errstr.str(), log_error);
285 DWORD procret = WaitForSingleObject(pi.hProcess, 1000);
286 if ( WAIT_OBJECT_0 != procret ) {
287 std::wstringstream errstr;
288 errstr << L
"Waiting for exiftool failed with error " << procret;
289 scope_logger.
Log(errstr.str(), log_error);
294 CloseHandle(pi.hProcess);
295 if (0 == CloseHandle(pi.hThread) ) {
296 std::wstringstream errstr;
297 errstr << L
"exiftool.exe did not finish correctly, error " << GetLastError();
298 scope_logger.
Log(errstr.str(), log_error);
parameters::Scope parameters
the Controller's own set of ScopeParameters
ScopeString basename
basename for image files
Thread-safe lock-free bool to signal a requested stop to the worker function currently executed in th...
ScopeNumber< bool > autosave
autosave all acquisitions (except live scan)
The master parameters class.
Simple exception class for Scope.
ScopeString date
current date
std::array< std::vector< std::wstring >, SCOPE_NAREAS > filenames
Keep track of filenames.
Stack stack
the StackParameters
std::array< std::unique_ptr< Area >, SCOPE_NAREAS > areas
holds AreaParameters for all areas.
ScopeNumber< bool > savelive
autosave live scan acquisitions
ScopeLogger scope_logger
the logger kept handy
std::wstring CreateFolder()
Create folder.Fformat is: "folder/date/time_runmode/".
std::array< ScopeNumber< uint32_t >, SCOPE_NAREAS > frames
number of frames in timeseries for each area
ScopeNumber< bool > compresstiff
write compressed TIFF
Base class for all Scope datatypes here, provides a uniform interface (and saves typing...).
void Enqueue(const T &elem)
Enqueues an element and notifies one waiting operation that queue is not empty.
Timeseries timeseries
the TimeseriesParameters
ScopeNumber< bool > usetifftags
write tiff tags for ImageJ etc.
Storage storage
the StorageParameters
A logger class to log various messages and user comments.
ControllerReturnStatus Run(StopCondition *const sc, const uint32_t &_area) override
Main function for running data conversion to TIFF and storage.
ScopeString folder
folder to Save into
ScopeNumber< double > spacing
Spacing between planes in microns.
ScopeValue< DaqMode > requested_mode
requested acquisition mode (see DaqModeHelper)
void Log(const std::wstring &message, const log_message_type &msgtype)
Logs a message.
In here all declarations for all kinds of datatypes Scope needs.
Impl(SynchronizedQueue< ScopeMessage< SCOPE_MULTIIMAGEPTR_T >> *const _iqueue, const parameters::Scope &_parameters)
Connect the input queue and take parameters.
virtual ControllerReturnStatus WaitForAll(const int32_t &_wait_time)
Wait for the futures of all async worker functions.
virtual void StopAll()
Request all async worker function to stop.
virtual void StopOne(const uint32_t &_a)
Request one async worker function to stop by settings its StopCondition to true.
#define DBOUT(s)
A debug output to the debug console.
void Save(const std::wstring &filename) const
Save all to file.
The implementation class of the StorageController.
void ScopeExceptionHandler(const std::string &_origin, const bool &_log, const bool &_showmessagebox, const bool &_trace, const bool &_rethrow)
Handles all exceptions and does nice logging.
Impl operator=(const Impl &i)
disable assignment
~Impl()
Stop the controller and interrupt thread if necessary.
A synchronized, thread-safe queue was modeled after ringbuffer example from boost?! and/or a Herb Sutter column?!
std::array< ScopeNumber< double >, SCOPE_NAREAS > totaltimes
total acquisition time for each area
ScopeString time
current time
ScopeValue< RunState > run_state
current RunState
void Set(const bool &_a=true)
void StopOne(const uint32_t &_a) override
We need to override here.
uint32_t runcounter
for continuous file numbering
Encodes multi images to TIFF using Windows Imaging Components.
Various helper functions and classes for Scope.
SynchronizedQueue< ScopeMessage< SCOPE_MULTIIMAGEPTR_T > > *const input_queue
Input queue with multi images from the PipelineController.
Base class for all controllers.
void InitializeEncoders(const bool &_dosave, const std::wstring &_foldername)
Creates and initializes the encoders.
T Dequeue()
Dequeues front element, waits indefinitely if queue is empty.
ScopeNumber< bool > saveparameters
Save ScopeParameters in xml file.
Impl(const Impl &i)
disable copy
std::array< std::unique_ptr< ScopeMultiImageEncoder >, SCOPE_NAREAS > encoders
the encoders (encapsulating the WIC stuff)
void FixTIFFTags()
Write correct Tiff flags into files (fix the ones that are by default written by the WIC...