Xmipp  v3.23.11-Nereus
Public Member Functions | Static Public Member Functions | List of all members
EERRenderer Class Reference

Public Member Functions

 EERRenderer ()
 
 ~EERRenderer ()
 
 EERRenderer (const EERRenderer &)
 
EERRendereroperator= (const EERRenderer &)
 
void setFramesOfInterest (int start, int end)
 
void read (const FileName &_fn_movie, int eer_upsampling)
 
int getNFrames ()
 
int getWidth ()
 
int getHeight ()
 
template<typename T >
long long renderFrames (int frame_start, int frame_end, MultidimArray< T > &image)
 

Static Public Member Functions

static void TIFFWarningHandler (const char *module, const char *fmt, va_list ap)
 
static void silenceTIFFWarnings ()
 
static bool isEER (const FileName &fn_movie)
 

Detailed Description

Definition at line 71 of file rwEER.cpp.

Constructor & Destructor Documentation

◆ EERRenderer() [1/2]

EERRenderer::EERRenderer ( )
inline

Definition at line 221 of file rwEER.cpp.

222  {
223  ready = false;
224  read_data = false;
225  buf = NULL;
226  preread_start = -1;
227  preread_end = -1;
228  eer_upsampling = 2;
229  }

◆ ~EERRenderer()

EERRenderer::~EERRenderer ( )
inline

Definition at line 231 of file rwEER.cpp.

232  {
233  if (buf != NULL)
234  free(buf);
235  }
free((char *) ob)

◆ EERRenderer() [2/2]

EERRenderer::EERRenderer ( const EERRenderer )
inline

Definition at line 238 of file rwEER.cpp.

239  {
240  REPORT_ERROR(ERR_NOT_IMPLEMENTED, "Copy constructor for EERRenderer not implemented yet.");
241  }
Case or algorithm not implemented yet.
Definition: xmipp_error.h:177
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211

Member Function Documentation

◆ getHeight()

int EERRenderer::getHeight ( )
inline

Definition at line 376 of file rwEER.cpp.

377  {
378  if (!ready)
379  REPORT_ERROR(ERR_LOGIC_ERROR, "EERRenderer::getNFrames called before ready.");
380 
381  return EER_IMAGE_HEIGHT << (eer_upsampling - 1);
382  }
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
Some logical error in the pipeline.
Definition: xmipp_error.h:147

◆ getNFrames()

int EERRenderer::getNFrames ( )
inline

Definition at line 360 of file rwEER.cpp.

361  {
362  if (!ready)
363  REPORT_ERROR(ERR_LOGIC_ERROR, "EERRenderer::getNFrames called before ready.");
364 
365  return nframes;
366  }
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
Some logical error in the pipeline.
Definition: xmipp_error.h:147

◆ getWidth()

int EERRenderer::getWidth ( )
inline

Definition at line 368 of file rwEER.cpp.

369  {
370  if (!ready)
371  REPORT_ERROR(ERR_LOGIC_ERROR, "EERRenderer::getNFrames called before ready.");
372 
373  return EER_IMAGE_WIDTH << (eer_upsampling - 1);
374  }
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
Some logical error in the pipeline.
Definition: xmipp_error.h:147

◆ isEER()

static bool EERRenderer::isEER ( const FileName fn_movie)
inlinestatic

Definition at line 551 of file rwEER.cpp.

552  {
553  FileName ext = fn_movie.getExtension();
554  return (ext == "eer" || ext == "ecc");
555  }
String getExtension() const

◆ operator=()

EERRenderer& EERRenderer::operator= ( const EERRenderer )
inline

Definition at line 243 of file rwEER.cpp.

244  {
245  REPORT_ERROR(ERR_NOT_IMPLEMENTED, "Copy assignment operator for EERRenderer not implemented yet.");
246  }
Case or algorithm not implemented yet.
Definition: xmipp_error.h:177
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211

◆ read()

void EERRenderer::read ( const FileName _fn_movie,
int  eer_upsampling 
)
inline

Definition at line 286 of file rwEER.cpp.

287  {
288  if (ready)
289  REPORT_ERROR(ERR_LOGIC_ERROR, "Logic error: you cannot recycle EERRenderer for multiple files (now)");
290 
291  if (eer_upsampling == 1 || eer_upsampling == 2 || eer_upsampling == 3)
292  this->eer_upsampling = eer_upsampling;
293  else
294  {
295  std::cerr << "EERRenderer::read: eer_upsampling = " << eer_upsampling << std::endl;
296  REPORT_ERROR(ERR_PARAM_INCORRECT, "EERRenderer::read: eer_upsampling must be 1, 2 or 3.");
297  }
298 
299  fn_movie = _fn_movie;
300 
301  // First of all, check the file size
302  FILE *fh = fopen(fn_movie.c_str(), "r");
303  if (fh == NULL)
304  REPORT_ERROR(ERR_IO_NOTOPEN, "Failed to open " + fn_movie);
305 
306  fseek(fh, 0, SEEK_END);
307  file_size = ftell(fh);
308  fseek(fh, 0, SEEK_SET);
309 
311 
312  // Try reading as TIFF
313  TIFF *ftiff = TIFFOpen(fn_movie.c_str(), "r");
314 
315  if (ftiff == NULL)
316  {
317  is_legacy = true;
318  is_7bit = false;
319  readLegacy(fh);
320  }
321  else
322  {
323  is_legacy = false;
324 
325  // Check width & size
326  int width, height;
327  uint16_t compression = 0;
328  TIFFGetField(ftiff, TIFFTAG_IMAGEWIDTH, &width);
329  TIFFGetField(ftiff, TIFFTAG_IMAGELENGTH, &height);
330  TIFFGetField(ftiff, TIFFTAG_COMPRESSION, &compression);
331 
332  #ifdef DEBUG_EER
333  printf("EER in TIFF: %s size = %ld, width = %d, height = %d, compression = %d\n", fn_movie.c_str(), file_size, width, height, compression);
334  #endif
335 
336  // TIA can write an EER file whose first page is a sum and compressoin == 1.
337  // This is not supported (yet). EPU never writes such movies.
338  if (compression == EERRenderer::TIFF_COMPRESSION_EER8bit)
339  is_7bit = false;
340  else if (compression == EERRenderer::TIFF_COMPRESSION_EER7bit)
341  is_7bit = true;
342  else
343  REPORT_ERROR(ERR_PARAM_INCORRECT, "Unknown compression scheme for EER " + integerToString(compression));
344 
345  if (width != EER_IMAGE_WIDTH || height != EER_IMAGE_HEIGHT)
346  REPORT_ERROR(ERR_PARAM_INCORRECT, "Currently we support only 4096x4096 pixel EER movies.");
347 
348  // Find the number of frames
349  nframes = TIFFNumberOfDirectories(ftiff);
350  TIFFClose(ftiff);
351  #ifdef DEBUG_EER
352  printf("EER in TIFF: %s nframes = %d\n", fn_movie.c_str(), nframes);
353  #endif
354  }
355 
356  fclose(fh);
357  ready = true;
358  }
Parameter incorrect.
Definition: xmipp_error.h:181
static void silenceTIFFWarnings()
Definition: rwEER.cpp:259
struct tiff TIFF
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
String integerToString(int I, int _width, char fill_with)
File cannot be open.
Definition: xmipp_error.h:137
Some logical error in the pipeline.
Definition: xmipp_error.h:147

◆ renderFrames()

template<typename T >
long long EERRenderer::renderFrames ( int  frame_start,
int  frame_end,
MultidimArray< T > &  image 
)
inline

Definition at line 389 of file rwEER.cpp.

390  {
391  if (!ready)
392  REPORT_ERROR(ERR_LOGIC_ERROR, "EERRenderer::renderNFrames called before ready.");
393 
394  lazyReadFrames();
395 
396  if (frame_start < 0 || frame_start >= getNFrames() ||
397  frame_end < frame_start || frame_end >= getNFrames())
398  {
399  std::cerr << "EERRenderer::renderFrames(frame_start = " << frame_start << ", frame_end = " << frame_end << "), NFrames = " << getNFrames() << std::endl;
400  REPORT_ERROR(ERR_PARAM_INCORRECT, "Invalid frame range was requested.");
401  }
402 
403  long long total_n_electron = 0;
404 
405  std::vector<unsigned int> positions;
406  std::vector<unsigned char> symbols;
407  image.initZeros(getHeight(), getWidth());
408 
409  for (int iframe = frame_start; iframe <= frame_end; iframe++)
410  {
411  RCTIC(TIMING_UNPACK_RLE);
412  if ((preread_start > 0 && iframe < preread_start) ||
413  (preread_end > 0 && iframe > preread_end))
414  {
415  std::cerr << "EERRenderer::renderFrames(frame_start = " << frame_start + 1 << ", frame_end = " << frame_end + 1<< "), NFrames = " << getNFrames() << " preread_start = " << preread_start + 1 << " prered_end = " << preread_end + 1<< std::endl;
416  REPORT_ERROR(ERR_LOGIC_ERROR, "Tried to render frames outside pre-read region");
417  }
418 
419  long long pos = frame_starts[iframe];
420  unsigned int n_pix = 0, n_electron = 0;
421  const int max_electrons = frame_sizes[iframe] * 2; // at 4 bits per electron (very permissive bound!)
422  if (positions.size() < max_electrons)
423  {
424  positions.resize(max_electrons);
425  symbols.resize(max_electrons);
426  }
427 
428  if (is_7bit)
429  {
430  unsigned int bit_pos = 0; // 4 K * 4 K * 11 bit << 2 ** 32
431  unsigned char p, s;
432 
433  while (true)
434  {
435  // Fetch 32 bits and unpack up to 2 chunks of 7 + 4 bits.
436  // This is faster than unpack 7 and 4 bits sequentially.
437  // Since the size of buf is larger than the actual size by the TIFF header size,
438  // it is always safe to read ahead.
439 
440  long long first_byte = pos + (bit_pos >> 3);
441  const unsigned int bit_offset_in_first_byte = bit_pos & 7; // 7 = 00000111 (same as % 8)
442  const unsigned int chunk = (*(unsigned int*)(buf + first_byte)) >> bit_offset_in_first_byte;
443 
444  p = (unsigned char)(chunk & 127); // 127 = 01111111
445  bit_pos += 7; // TODO: we can remove this for further speed.
446  n_pix += p;
447  if (n_pix >= EER_IMAGE_PIXELS) break;
448  if (p == 127) continue; // this should be rare.
449 
450  s = (unsigned char)((chunk >> 7) & 15) ^ 0x0A; // 15 = 00001111; See below for 0x0A
451  bit_pos += 4;
452  positions[n_electron] = n_pix;
453  symbols[n_electron] = s;
454  n_electron++;
455  n_pix++;
456 
457  p = (unsigned char)((chunk >> 11) & 127); // 127 = 01111111
458  bit_pos += 7;
459  n_pix += p;
460  if (n_pix >= EER_IMAGE_PIXELS) break;
461  if (p == 127) continue;
462 
463  s = (unsigned char)((chunk >> 18) & 15) ^ 0x0A; // 15 = 00001111; See below for 0x0A
464  bit_pos += 4;
465  positions[n_electron] = n_pix;
466  symbols[n_electron] = s;
467  n_electron++;
468  n_pix++;
469  }
470  }
471  else
472  {
473  // unpack every two symbols = 12 bit * 2 = 24 bit = 3 byte
474  // high <- |bbbbBBBB|BBBBaaaa|AAAAAAAA| -> low
475  // With SIMD intrinsics at the SSSE3 level, we can unpack 10 symbols (120 bits) simultaneously.
476  unsigned char p1, p2, s1, s2;
477 
478  const long long pos_limit = frame_starts[iframe] + frame_sizes[iframe];
479  // Because there is a footer, it is safe to go beyond the limit by two bytes.
480  while (pos < pos_limit)
481  {
482  // symbol is bit tricky. 0000YyXx; Y and X must be flipped.
483  p1 = buf[pos];
484  s1 = (buf[pos + 1] & 0x0F) ^ 0x0A; // 0x0F = 00001111, 0x0A = 00001010
485 
486  p2 = (buf[pos + 1] >> 4) | (buf[pos + 2] << 4);
487  s2 = (buf[pos + 2] >> 4) ^ 0x0A;
488 
489  // Note the order. Add p before checking the size and placing a new electron.
490  n_pix += p1;
491  if (n_pix >= EER_IMAGE_PIXELS) break;
492  if (p1 < 255)
493  {
494  positions[n_electron] = n_pix;
495  symbols[n_electron] = s1;
496  n_electron++;
497  n_pix++;
498  }
499 
500  n_pix += p2;
501  if (n_pix >= EER_IMAGE_PIXELS) break;
502  if (p2 < 255)
503  {
504  positions[n_electron] = n_pix;
505  symbols[n_electron] = s2;
506  n_electron++;
507  n_pix++;
508  }
509  #ifdef DEBUG_EER_DETAIL
510  printf("%d: %u %u, %u %u %d\n", pos, p1, s1, p2, s2, n_pix);
511  #endif
512  pos += 3;
513  }
514  }
515 
516  if (n_pix != EER_IMAGE_PIXELS)
517  {
518  std::cerr << "WARNING: The number of pixels is not right in " + fn_movie + " frame " + integerToString(iframe + 1) + ". Probably this frame is corrupted. This frame is skipped." << std::endl;
519  continue;
520  }
521 
522  RCTOC(TIMING_UNPACK_RLE);
523 
524  RCTIC(TIMING_RENDER_ELECTRONS);
525  if (eer_upsampling == 3)
526  render16K(image, positions, symbols, n_electron);
527  else if (eer_upsampling == 2)
528  render8K(image, positions, symbols, n_electron);
529  else if (eer_upsampling == 1)
530  render4K(image, positions, symbols, n_electron);
531  else
532  REPORT_ERROR(ERR_LOGIC_ERROR, "Invalid EER upsample");
533  RCTOC(TIMING_RENDER_ELECTRONS);
534 
535  total_n_electron += n_electron;
536  #ifdef DEBUG_EER
537  printf("Decoded %lld electrons / %d pixels from frame %5d.\n", n_electron, n_pix, iframe);
538  #endif
539  }
540  #ifdef DEBUG_EER
541  printf("Decoded %lld electrons in total.\n", total_n_electron);
542  #endif
543 
544  #ifdef TIMING
545  EERtimer.printTimes(false);
546  #endif
547 
548  return total_n_electron;
549  }
Parameter incorrect.
Definition: xmipp_error.h:181
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
int getHeight()
Definition: rwEER.cpp:376
String integerToString(int I, int _width, char fill_with)
#define RCTOC(label)
Definition: rwEER.cpp:68
int getWidth()
Definition: rwEER.cpp:368
void initZeros(const MultidimArray< T1 > &op)
int getNFrames()
Definition: rwEER.cpp:360
#define RCTIC(label)
Definition: rwEER.cpp:67
Some logical error in the pipeline.
Definition: xmipp_error.h:147

◆ setFramesOfInterest()

void EERRenderer::setFramesOfInterest ( int  start,
int  end 
)
inline

Definition at line 275 of file rwEER.cpp.

276  {
277  if (is_legacy)
278  return;
279 
280  if (read_data)
281  REPORT_ERROR(ERR_LOGIC_ERROR, "Logic error in EERRenderer::setFramesOfInterest(). This must be set before rendering.");
282  preread_start = start - 1;
283  preread_end = end - 1;
284  }
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
Some logical error in the pipeline.
Definition: xmipp_error.h:147

◆ silenceTIFFWarnings()

static void EERRenderer::silenceTIFFWarnings ( )
inlinestatic

Definition at line 259 of file rwEER.cpp.

260  {
261  if (prevTIFFWarningHandler == NULL)
262  {
263  // Thread safety issue:
264  // Calling this simultaneously is safe but
265  TIFFErrorHandler prev = TIFFSetWarningHandler(EERRenderer::TIFFWarningHandler);
266 
267  // we have to make sure prevTIFFWarningHandler does NOT become our own TIFFWarningHandler
268  // to avoid an infinite loop.
270  prevTIFFWarningHandler = prev;
271  }
272  }
static void TIFFWarningHandler(const char *module, const char *fmt, va_list ap)
Definition: rwEER.cpp:249

◆ TIFFWarningHandler()

static void EERRenderer::TIFFWarningHandler ( const char *  module,
const char *  fmt,
va_list  ap 
)
inlinestatic

Definition at line 249 of file rwEER.cpp.

250  {
251  // Silence warnings for private tags
252  if (strcmp("Unknown field with tag %d (0x%x) encountered", fmt) == 0)
253  return;
254 
255  if (prevTIFFWarningHandler != NULL)
256  prevTIFFWarningHandler(module, fmt, ap);
257  }

The documentation for this class was generated from the following file: