18 po::options_description control(
"zfits");
20 (
"in", var<string>()->required(),
"")
21 (
"out", var<string>(),
"")
23 (
"force,f", var<string>(),
"Force overwrite of output file")
26 po::positional_options_description p;
37 "zfits - A fits compressor\n" 40 "Usage: zfits [-d] input.fits[.gz] [output.zf]\n";
45 string ReplaceEnd(
const string &
str,
const string &expr,
const string &repl)
49 const size_t p = out.rfind(expr);
50 if (p==out.size()-expr.length())
51 out.replace(p, expr.length(), repl);
62 string out =
ReplaceEnd(name,
".fits",
".zfits");
66 int Compress(
const string &ifile,
const string &ofile)
95 map<size_t, col_t> columns;
98 for (
auto it=cols.begin(); it!=cols.end(); it++)
102 c.offset = it->second.offset;
103 c.size = it->second.size;
104 c.num = it->second.num;
108 columns[c.offset] = c;
110 row_tot += c.size*c.num;
116 header.resize(f.tellg());
119 f.read((
char*)header.c_str(), header.size());
125 const size_t hlen = 0;
127 size_t hs = header.size();
130 fout.write((
char*)&hlen,
sizeof(
size_t));
131 fout.write((
char*)&hs,
sizeof(
size_t));
132 fout.write(header.c_str(), header.size());
134 tot += header.size();
135 com += header.size()+2+2*
sizeof(size_t);
142 vector<char> cache(row_tot);
146 char *out = cache.data();
149 vector<uint8_t> mask(cols.size()/8 + 1);
153 for (
auto it=columns.begin(); it!=columns.end(); it++, icol++)
156 const size_t len_col = it->second.size * it->second.num;
159 int16_t *ptr = (int16_t*)it->second.ptr;
178 if (len_col>32 && it->second.size==2)
190 if (buf.size()<len_col)
193 memcpy(out, buf.c_str(), buf.size());
197 const uint64_t bit = (icol%8);
198 mask[icol/8] |= (1<<bit);
205 memcpy(out, (
char*)ptr, len_col);
210 const size_t sz = out-cache.data();
214 com += sz + mask.size();
217 fout.write((
char*)mask.data(), mask.size());
218 fout.write(cache.data(), sz);
227 cout <<
"\r" << setprecision(0) << setw(3) << 100*proc <<
"% [" << setprecision(1) << setw(5) << 100.*com/tot <<
"%] cpu:" << sec <<
"s in:" << tot/1000000/elep <<
"MB/s" << flush;
233 cout << setprecision(0) <<
"\r100% [" << setprecision(1) << setw(5) << 100.*com/tot <<
"%] cpu:" << sec <<
"s in:" << tot/1000000/elep <<
"MB/s" << endl;
239 void revcpy(
char *dest,
const char *src,
int num)
241 const char *pend = src + num*N;
242 for (
const char *ptr = src; ptr<pend; ptr+=N, dest+=N)
243 reverse_copy(ptr, ptr+N, dest);
252 ofstream fout(ofile);
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.");
262 fin.read((
char*)&hlen,
sizeof(
size_t));
264 throw runtime_error(
"Only Version-zero files supported.");
268 fin.read((
char*)&hs,
sizeof(
size_t));
270 throw runtime_error(
"Could not access header size.");
277 fin.read((
char*)header.c_str(), header.size());
278 fout.write((
char*)header.c_str(), header.size());
280 throw runtime_error(
"Could not read full header");
282 string templ(
"tmpXXXXXX");
283 int fd = mkstemp((
char*)templ.c_str());
284 const ssize_t rc = write(fd, header.c_str(), header.size());
288 throw runtime_error(
"Could not write to temporary file: "+
string(strerror(errno)));
293 remove(templ.c_str());
299 map<size_t, fits::Table::Column> columns;
300 for (
auto it=cols.begin(); it!=cols.end(); it++)
302 columns[it->second.offset] = it->second;
303 row_tot += it->second.num*it->second.size;
310 size_t com = 2+hs+2*
sizeof(size_t);
313 const size_t masklen = cols.size()/8+1;
316 vector<char> buf(row_tot+masklen);
317 vector<char> swap(row_tot);
320 const uint64_t nrows = info.
GetUInt(
"NAXIS2");
325 for (uint32_t irow=0; irow<nrows; irow++)
327 fin.read(buf.data()+offset, buf.size()-offset);
329 const uint8_t *mask =
reinterpret_cast<uint8_t*
>(buf.data());
332 char *ptr = swap.data();
335 for (
auto it=columns.begin(); it!= columns.end(); it++, icol++)
337 const size_t &num = it->second.num;
338 const size_t &
size = it->second.size;
340 if (mask[icol/8]&(1<<(icol%8)))
344 vector<uint16_t> out(num*size/2);
345 int len =
Huffman::Decode((uint8_t*)buf.data()+offset, buf.size()-offset, out);
347 throw runtime_error(
"Decoding failed.");
353 revcpy<2>(ptr, (
char*)out.data(), num);
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;
371 com += offset+masklen;
374 fout.write((
char*)swap.data(), swap.size());
376 memmove(buf.data(), buf.data()+offset, buf.size()-offset);
377 offset = buf.size()-offset;
380 throw runtime_error(
"Error writing to output file");
382 const float proc = float(irow)/nrows;
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;
392 cout << setprecision(0) <<
"\r100% [" << setprecision(1) << setw(5) << 100.*com/tot <<
"%] cpu:" << sec <<
"s out:" << tot/1000000/elep <<
"MB/s" << endl;
397 int main(
int argc,
const char **argv)
406 const bool decomp = conf.
Get<
bool>(
"decompress");
408 const string ifile = conf.
Get<
string>(
"in");
409 const string ofile = conf.
Has(
"out") ? conf.
Get<
string>(
"out") :
ReplaceExt(ifile, decomp);
void SetupConfiguration(Configuration &conf)
void * SetPtrAddress(const std::string &name)
int Compress(const string &ifile, const string &ofile)
std::map< std::string, Column > Columns
uint64_t GetUInt(const std::string &key) const
Adds some functionality to boost::posix_time::ptime for our needs.
void SetPrintUsage(const std::function< void(void)> &func)
T Get(const std::string &var)
po::typed_value< bool > * po_switch()
int64_t Decode(const uint8_t *bufin, size_t bufinlen, std::vector< uint16_t > &pbufout)
string ReplaceEnd(const string &str, const string &expr, const string &repl)
void SetArgumentPositions(const po::positional_options_description &desc)
virtual size_t GetNumRows() const
int main(int argc, const char **argv)
void revcpy(char *dest, const char *src, int num)
bool Encode(std::string &bufout, const uint16_t *bufin, size_t bufinlen)
bool GetNextRow(bool check=true)
bool Has(const std::string &var)
void AddOptions(const po::options_description &opt, bool visible=true)
string ReplaceExt(const string &name, bool decomp)
Commandline parsing, resource file parsing and database access.
const Table::Columns & GetColumns() const
int Decompress(const string &ifile, const string &ofile)
bool DoParse(int argc, const char **argv, const std::function< void()> &func=std::function< void()>())
virtual bool GetRow(size_t row, bool check=true)