FACT++  1.0
int main ( int  argc,
const char **  argv 
)

Definition at line 1505 of file fitsDecompressor.cc.

References ofits::AddColumn(), buffer, ofits::close(), count, Configuration::DoParse(), Configuration::Get(), ofits::GetChecksumData(), fits::GetColumns(), fits::GetKeys(), fits::GetNextRow(), zfits::GetNumRows(), fits::GetSortedColumns(), fits::GetStr(), fits::GetUInt(), Configuration::Has(), fits::HasKey(), i, fits::IsCompressedFITS(), zfits::IsFileOk(), ofits::open(), printHelp(), printUsage(), ofits::SetKeyComment(), Configuration::SetPrintUsage(), fits::SetPtrAddress(), setupConfiguration(), str, type, Configuration::Vec(), ofits::WriteRow(), and ofits::WriteTableHeader().

1506 {
1507  Configuration conf(argv[0]);
1508  conf.SetPrintUsage(printUsage);
1509  setupConfiguration(conf);
1510 
1511  if (!conf.DoParse(argc, argv, printHelp))
1512  return -1;
1513 
1514  //initialize the file names to nothing.
1515  string fileNameIn = "";
1516  string fileNameOut = "";
1517  string drsFileName = "";
1518  uint32_t numRowsPerTile = 100;
1519  bool displayText=true;
1520 
1521  //parse configuration
1522  if (conf.Get<bool>("quiet")) displayText = false;
1523  const vector<string> inputFileNameVec = conf.Vec<string>("inputFile");
1524  if (inputFileNameVec.size() != 1)
1525  {
1526  cout << "Error: ";
1527  if (inputFileNameVec.size() == 0) cout << "no";
1528  else cout << inputFileNameVec.size();
1529  cout << " input file(s) given. Expected one. Aborting. Input:" << endl;;
1530  for (unsigned int i=0;i<inputFileNameVec.size(); i++)
1531  cout << inputFileNameVec[i] << endl;
1532  return -1;
1533  }
1534 
1535  //Assign the input filename
1536  fileNameIn = inputFileNameVec[0];
1537 
1538  //Check if we have a drs calib too
1539  if (conf.Has("drs")) drsFileName = conf.Get<string>("drs");
1540 
1541  //Should we verify the data ?
1542  bool verifyDataPlease = false;
1543  if (conf.Has("verify")) verifyDataPlease = conf.Get<bool>("verify");
1544 
1545 
1546  //should we use a specific output filename ?
1547  if (conf.Has("output"))
1548  fileNameOut = conf.Get<string>("output");
1549  else
1550  {
1551  size_t pos = fileNameIn.find(".fits.fz");
1552  if (pos == string::npos)
1553  {
1554  cout << "ERROR: input file does not seems ot be fits. Aborting." << endl;
1555  return -1;
1556  }
1557  fileNameOut = fileNameIn.substr(0, pos) + ".fits";
1558  }
1559 
1560 
1561  //should we use specific compression on some columns ?
1562  const vector<string> columnsCompression = conf.Vec<string>("compression");
1563 
1564  //split up values between column names and compression scheme
1565  vector<std::pair<string, string>> compressions;
1566  for (unsigned int i=0;i<columnsCompression.size();i++)
1567  {
1568  size_t pos = columnsCompression[i].find_first_of("=");
1569  if (pos == string::npos)
1570  {
1571  cout << "ERROR: Something wrong occured while parsing " << columnsCompression[i] << ". Aborting." << endl;
1572  return -1;
1573  }
1574  string comp = columnsCompression[i].substr(pos+1);
1575  if (comp != "UNCOMPRESSED" && comp != "AMPLITUDE" && comp != "HUFFMAN" &&
1576  comp != "SMOOTHMAN" && comp != "INT_WAVELET")
1577  {
1578  cout << "Unkown compression scheme requested (" << comp << "). Aborting." << endl;
1579  return -1;
1580  }
1581  compressions.push_back(make_pair(columnsCompression[i].substr(0, pos), comp));
1582  }
1583 
1584  //How many rows per tile should we use ?
1585  if (conf.Has("rowPerTile")) numRowsPerTile = conf.Get<unsigned int>("rowPerTile");
1586 
1588  // Done reading configuration. Open relevant files
1590 
1591 
1592  //Open input's fits file
1593  factfits inFile(fileNameIn, "", "Events", false);
1594 
1595  if (!inFile.IsCompressedFITS())
1596  {
1597  cout << "ERROR: input file is NOT a compressed fits. Cannot be decompressed: Aborting." << endl;
1598  return -1;
1599  }
1600 
1601  //decide how many tiles should be put in the compressed file
1602  uint32_t originalNumRows = inFile.GetNumRows();
1603  uint32_t numTiles = (originalNumRows%numRowsPerTile) ? (originalNumRows/numRowsPerTile)+1 : originalNumRows/numRowsPerTile;
1604 // CompressedFitsWriter outFile(numTiles, numRowsPerTile);
1605 
1606  //should we use a specific number of threads for compressing ?
1607  unsigned int numThreads = 1;
1608  if (conf.Has("threads"))
1609  {
1610  numThreads = conf.Get<unsigned int>("threads");
1611 // outFile.setNumWorkingThreads(numThreads);
1612  }
1613 
1614 
1615 
1616  //Because the file to open MUST be given by the constructor, I must use a pointer instead
1617  factfits* drsFile = NULL;
1618  //try to open the Drs file. If any.
1619  if (drsFileName != "")
1620  {
1621  try
1622  {
1623  drsFile = new factfits(drsFileName);
1624  }
1625  catch (...)
1626  {
1627  cout << "Error: could not open " << drsFileName << " for calibration" << endl;
1628  return -1;
1629  }
1630  }
1631 
1632  if (displayText)
1633  {
1634  cout << endl;
1635  cout << "**********************" << endl;
1636  cout << "Will decompress from : " << fileNameIn << endl;
1637  cout << "to : " << fileNameOut << endl;
1638  cout << "**********************" << endl;
1639  cout << endl;
1640  }
1641 
1643  // Done opening input files. Allocate memory and configure output file
1645 
1646  //allocate the buffer for temporary storage of each read/written row
1647  uint32_t rowWidth = inFile.GetUInt("ZNAXIS1");
1648  char* buffer = new char[rowWidth + 12];
1649  memset(buffer, 0, 4);
1650  buffer = buffer+4;
1651 
1652  //get the source columns
1653  const fits::Table::Columns& columns = inFile.GetColumns();
1654  const fits::Table::SortedColumns& sortedColumns = inFile.GetSortedColumns();
1655  if (displayText)
1656  cout << "Input file has " << columns.size() << " columns and " << inFile.GetNumRows() << " rows" << endl;
1657 
1658 
1660  // Done configuring compression. Do the real job now !
1662  vector<void*> readPointers;
1663  vector<int32_t> readOffsets;
1664  vector<int32_t> readElemSize;
1665  vector<int32_t> readNumElems;
1666  //Get table name for later use in case the compressed file is to be verified
1667  string tableName = inFile.GetStr("EXTNAME");
1668 
1669 
1670  //and the header of the compressed file
1671  const fits::Table::Keys& header2 = inFile.GetKeys();
1672 
1673  //get a non-compressed writer
1674  ofits reconstructedFile;
1675 
1676  //figure out its name: /dev/null unless otherwise specified
1677  string reconstructedName = fileNameOut;
1678  reconstructedFile.open(reconstructedName.c_str(), false);
1679 
1680  //reconstruct the original columns from the compressed file.
1681  string origChecksumStr;
1682  string origDatasum;
1683 
1684  //reset tablename value so that it is re-read from compressed table's header
1685  tableName = "";
1686 
1687  /************************************************************************************
1688  * Reconstruction setup done. Rebuild original header
1689  ************************************************************************************/
1690 
1691  //re-tranlate the keys
1692  for (fits::Table::Keys::const_iterator it=header2.begin(); it!= header2.end(); it++)
1693  {
1694  string k = it->first;
1695  if (k == "XTENSION" || k == "BITPIX" || k == "PCOUNT" || k == "GCOUNT" ||
1696  k == "TFIELDS" || k == "ZTABLE" || k == "ZNAXIS1" || k == "ZNAXIS2" ||
1697  k == "ZHEAPPTR" || k == "ZPCOUNT" || k == "ZTILELEN" || k == "THEAP" ||
1698  k == "CHECKSUM" || k == "DATASUM" || k == "FCTCPVER" || k == "ZHEAP")
1699  {
1700  continue;
1701  }
1702 
1703  if (k == "ZCHKSUM")
1704  {
1705  reconstructedFile.SetKeyComment("CHECKSUM", it->second.comment);
1706  origChecksumStr = it->second.value;
1707  continue;
1708  }
1709  if (k == "RAWSUM")
1710  {
1711  continue;
1712  }
1713 
1714  if (k == "ZDTASUM")
1715  {
1716  reconstructedFile.SetKeyComment("DATASUM", it->second.comment);
1717  origDatasum = it->second.value;
1718  continue;
1719  }
1720 
1721  if (k == "EXTNAME")
1722  {
1723  tableName = it->second.value;
1724  }
1725 
1726  k = k.substr(0,5);
1727 
1728  if (k == "TTYPE")
1729  {//we have an original column name here.
1730  //manually deal with these in order to preserve the ordering (easier than re-constructing yet another list on the fly)
1731  continue;
1732  }
1733 
1734  if (k == "TFORM" || k == "NAXIS" || k == "ZCTYP" )
1735  {
1736  continue;
1737  }
1738 
1739  if (k == "ZFORM" || k == "ZTYPE")
1740  {
1741  string tmpKey = it->second.fitsString;
1742  tmpKey[0] = 'T';
1743  reconstructedFile.SetKeyFromFitsString(tmpKey);
1744  continue;
1745  }
1746 
1747  reconstructedFile.SetKeyFromFitsString(it->second.fitsString);
1748  }
1749 
1750  if (tableName == "")
1751  {
1752  cout << "Error: table name from file " << fileNameOut << " could not be found. Aborting" << endl;
1753  return -1;
1754  }
1755 
1756  //Restore the original columns
1757  for (uint32_t numCol=1; numCol<10000; numCol++)
1758  {
1759  ostringstream str;
1760  str << numCol;
1761  if (!inFile.HasKey("TTYPE"+str.str())) break;
1762 
1763  string ttype = inFile.GetStr("TTYPE"+str.str());
1764  string tform = inFile.GetStr("ZFORM"+str.str());
1765  char type = tform[tform.size()-1];
1766  string number = tform.substr(0, tform.size()-1);
1767  int numElems = atoi(number.c_str());
1768 
1769  if (number == "") numElems=1;
1770 
1771  reconstructedFile.AddColumn(numElems, type, ttype, "", "", false);
1772  }
1773 
1774  reconstructedFile.WriteTableHeader(tableName.c_str());
1775 
1776  /************************************************************************************
1777  * Original header restored. Do the data
1778  ************************************************************************************/
1779 
1780  //set pointers to the readout data to later be able to gather it to "buffer".
1781  readPointers.clear();
1782  readOffsets.clear();
1783  readElemSize.clear();
1784  readNumElems.clear();
1785  for (fits::Table::Columns::const_iterator it=columns.begin(); it!= columns.end(); it++)
1786  {
1787  readPointers.push_back(inFile.SetPtrAddress(it->first));
1788  readOffsets.push_back(it->second.offset);
1789  readElemSize.push_back(it->second.size);
1790  readNumElems.push_back(it->second.num);
1791  }
1792 
1793  //do the actual reconstruction work
1794  uint32_t i=1;
1795  while (i<=inFile.GetNumRows() && inFile.GetNextRow())
1796  {
1797  int count=0;
1798  for (fits::Table::Columns::const_iterator it=columns.begin(); it!= columns.end();it++)
1799  {
1800  memcpy(&buffer[readOffsets[count]], readPointers[count], readElemSize[count]*readNumElems[count]);
1801  count++;
1802  }
1803  if (displayText) cout << "\r Row " << i << flush;
1804  reconstructedFile.WriteRow(buffer, rowWidth);
1805  if (!reconstructedFile.good())
1806  {
1807  cout << "ERROR: no space left on device (probably)" << endl;
1808  return -1;
1809  }
1810  i++;
1811  }
1812 
1813  if (displayText) cout << endl;
1814 
1815  //close reconstruction input and output
1816 // Do NOT close the verify file, otherwise data cannot be flushed to copy file
1817 // verifyFile.close();
1818  if (!inFile.IsFileOk())
1819  cout << "ERROR: file checksums seems wrong" << endl;
1820 
1821  if (!reconstructedFile.close())
1822  {
1823  cout << "ERROR: disk probably full..." <<endl;
1824  return -1;
1825  }
1826 
1827  //get original and reconstructed checksum and datasum
1828  std::pair<string, int> origChecksum = make_pair(origChecksumStr, atoi(origDatasum.c_str()));
1829  std::pair<string, int> newChecksum = reconstructedFile.GetChecksumData();
1830 
1831  //verify that no mistake was made
1832  if (origChecksum.second != newChecksum.second)
1833  {
1834  cout << "ERROR: datasums are NOT identical: " << (uint32_t)(origChecksum.second) << " vs " << (uint32_t)(newChecksum.second) << endl;
1835  return -1;
1836  }
1837  if (origChecksum.first != newChecksum.first)
1838  {
1839  cout << "WARNING: checksums are NOT Identical: " << origChecksum.first << " vs " << newChecksum.first << endl;
1840  }
1841  else
1842  {
1843  if (true) cout << "Ok" << endl;
1844  }
1845 
1846  buffer = buffer-4;
1847  delete[] buffer;
1848  return 0;
1849 }
std::vector< Column > SortedColumns
Definition: fits.h:114
std::map< std::string, Column > Columns
Definition: fits.h:113
std::pair< std::string, int > GetChecksumData()
Definition: ofits.h:1012
int i
Definition: db_dim_client.c:21
char str[80]
Definition: test_client.c:7
bool SetKeyComment(const std::string &key, const std::string &comment)
Definition: ofits.h:430
virtual bool AddColumn(uint32_t cnt, char typechar, const std::string &name, const std::string &unit, const std::string &comment="", bool addHeaderKeys=true)
Definition: ofits.h:596
void printHelp()
void setupConfiguration(Configuration &conf)
virtual void open(const char *filename, bool addEXTNAMEKey=true)
Definition: ofits.h:390
Definition: ofits.h:29
int type
std::map< std::string, Entry > Keys
Definition: fits.h:112
virtual bool close()
Definition: ofits.h:984
void printUsage()
Commandline parsing, resource file parsing and database access.
Definition: Configuration.h:9
int buffer[BUFFSIZE]
Definition: db_dim_client.c:14
int count
Definition: db_dim_server.c:18
virtual bool WriteTableHeader(const char *name="DATA")
Definition: ofits.h:844
virtual bool WriteRow(const void *ptr, size_t cnt, bool byte_swap=true)
Definition: ofits.h:884

+ Here is the call graph for this function: