FACT++  1.0
int Decompress ( const string &  ifile,
const string &  ofile 
)

Definition at line 246 of file zfits.cc.

References Huffman::Decode(), fits::GetColumns(), fits::GetUInt(), size, start(), and Time::UnixTime().

Referenced by main().

247 {
248  // open a fits file
249  ifstream fin(ifile);
250 
251  // open output file
252  ofstream fout(ofile);
253 
254  // get and check magic number
255  unsigned char m[2];
256  fin.read((char*)m, 2);
257  if (m[0]!='z'+128 || m[1]!='f'+128)
258  throw runtime_error("File not a compressed fits file.");
259 
260  // get length of additional header information
261  size_t hlen = 0;
262  fin.read((char*)&hlen, sizeof(size_t));
263  if (hlen>0)
264  throw runtime_error("Only Version-zero files supported.");
265 
266  // get size of FITS header
267  size_t hs = 0;
268  fin.read((char*)&hs, sizeof(size_t));
269  if (!fin)
270  throw runtime_error("Could not access header size.");
271 
272  // copy the header from the input to the output file
273  // and prefix the output file as a compressed fits file
274  string header;
275  header.resize(hs);
276 
277  fin.read((char*)header.c_str(), header.size());
278  fout.write((char*)header.c_str(), header.size());
279  if (!fin)
280  throw runtime_error("Could not read full header");
281 
282  string templ("tmpXXXXXX");
283  int fd = mkstemp((char*)templ.c_str());
284  const ssize_t rc = write(fd, header.c_str(), header.size());
285  close(fd);
286 
287  if (rc<0)
288  throw runtime_error("Could not write to temporary file: "+string(strerror(errno)));
289 
290  // open the output file to get the header parsed
291  fits info(templ);
292 
293  remove(templ.c_str());
294 
295  // get the maximum size of one row and a list
296  // of all columns ordered by their offset
297  size_t row_tot = 0;
298  const fits::Table::Columns &cols = info.GetColumns();
299  map<size_t, fits::Table::Column> columns;
300  for (auto it=cols.begin(); it!=cols.end(); it++)
301  {
302  columns[it->second.offset] = it->second;
303  row_tot += it->second.num*it->second.size;
304  }
305 
306  // very simple timer
307  double sec = 0;
308  double frac = 0;
309 
310  size_t com = 2+hs+2*sizeof(size_t);
311  size_t tot = hs;
312 
313  const size_t masklen = cols.size()/8+1;
314 
315  // loop over all rows
316  vector<char> buf(row_tot+masklen);
317  vector<char> swap(row_tot);
318  uint32_t offset = 0;
319 
320  const uint64_t nrows = info.GetUInt("NAXIS2");
321 
322  Time start;
323 
324  cout << fixed;
325  for (uint32_t irow=0; irow<nrows; irow++)
326  {
327  fin.read(buf.data()+offset, buf.size()-offset);
328 
329  const uint8_t *mask = reinterpret_cast<uint8_t*>(buf.data());
330  offset = masklen;
331 
332  char *ptr = swap.data();
333 
334  uint32_t icol = 0;
335  for (auto it=columns.begin(); it!= columns.end(); it++, icol++)
336  {
337  const size_t &num = it->second.num;
338  const size_t &size = it->second.size;
339 
340  if (mask[icol/8]&(1<<(icol%8)))
341  {
342  Time now;
343 
344  vector<uint16_t> out(num*size/2);
345  int len = Huffman::Decode((uint8_t*)buf.data()+offset, buf.size()-offset, out);
346  if (len<0)
347  throw runtime_error("Decoding failed.");
348 
349  sec += Time().UnixTime()-now.UnixTime();
350 
351  offset += len;
352 
353  revcpy<2>(ptr, (char*)out.data(), num);
354  }
355  else
356  {
357  switch (size)
358  {
359  case 1: memcpy (ptr, buf.data()+offset, num*size); break;
360  case 2: revcpy<2>(ptr, buf.data()+offset, num); break;
361  case 4: revcpy<4>(ptr, buf.data()+offset, num); break;
362  case 8: revcpy<8>(ptr, buf.data()+offset, num); break;
363  }
364 
365  offset += num*size;
366  }
367 
368  ptr += num*size;
369  }
370 
371  com += offset+masklen;
372  tot += row_tot;
373 
374  fout.write((char*)swap.data(), swap.size());
375 
376  memmove(buf.data(), buf.data()+offset, buf.size()-offset);
377  offset = buf.size()-offset;
378 
379  if (!fout)
380  throw runtime_error("Error writing to output file");
381 
382  const float proc = float(irow)/nrows;
383  if (proc>frac)
384  {
385  const double elep = Time().UnixTime()-start.UnixTime();
386  cout << "\r" << setprecision(0) << setw(3) << 100*proc << "% [" << setprecision(1) << setw(5) << 100.*com/tot << "%] cpu:" << sec << "s out:" << tot/1000000/elep << "MB/s" << flush;
387  frac += 0.01;
388  }
389  }
390 
391  const double elep = Time().UnixTime()-start.UnixTime();
392  cout << setprecision(0) << "\r100% [" << setprecision(1) << setw(5) << 100.*com/tot << "%] cpu:" << sec << "s out:" << tot/1000000/elep << "MB/s" << endl;
393 
394  return 0;
395 }
int start(int initState)
Definition: feeserver.c:1740
std::map< std::string, Column > Columns
Definition: fits.h:113
Adds some functionality to boost::posix_time::ptime for our needs.
Definition: Time.h:30
int64_t Decode(const uint8_t *bufin, size_t bufinlen, std::vector< uint16_t > &pbufout)
Definition: huffman.h:401
Definition: fits.h:54
double UnixTime() const
Definition: Time.cc:195
int size
Definition: db_dim_server.c:17

+ Here is the call graph for this function:

+ Here is the caller graph for this function: