#include "EleFitsUtils/ProgramOptions.h"
#include "ElementsKernel/ProgramHeaders.h"
#include <boost/program_options.hpp>
#include <map>
#include <string>
#include "EleFitsData/TestColumn.h"
#include "EleFitsData/TestRaster.h"
#include "EleFitsData/TestRecord.h"
#include "EleFits/MefFile.h"
using namespace Euclid;
using boost::program_options::options_description;
using boost::program_options::value;
using boost::program_options::variable_value;
static Elements::Logging logger = Elements::Logging::getLogger("EleFitsTutorial");
struct TutoRecords {
Fits::Record<std::string> stringRecord;
Fits::Record<int> intRecord;
Fits::Record<float> floatRecord;
Fits::Record<std::complex<double>> complexRecord;
};
struct TutoRasters {
Fits::VecRaster<std::int16_t, 2> int16Raster2D;
Fits::VecRaster<std::int32_t, 3> int32Raster3D;
Fits::VecRaster<std::int64_t, 4> int64Raster4D;
};
struct TutoColumns {
Fits::VecColumn<std::string> stringColumn;
Fits::VecColumn<std::int32_t> int32Column;
Fits::VecColumn<float> float32Column;
};
TutoRecords createRecords();
TutoRasters createRasters();
TutoColumns createColumns();
void writeRecords(const Fits::Header& h);
void readRecords(const Fits::Header& h);
void readRaster(const Fits::ImageRaster& du);
void readColumns(const Fits::BintableColumns& du);
TutoRecords createRecords() {
logger.info(" Creating records...");
Fits::Record<std::string> stringRecord("STRING", "VALUE", "unit", "comment");
Fits::Record<int> intRecord("INT", 0);
Fits::Record<float> floatRecord {"FLOAT", 3.14F, "", "A piece of Pi"};
auto complexRecord = Fits::Test::generateRandomRecord<std::complex<double>>("COMPLEX");
return {stringRecord, intRecord, floatRecord, complexRecord};
}
TutoRasters createRasters() {
logger.info(" Creating rasters...");
Fits::VecRaster<std::int16_t, 2> int16Raster2D({4, 3});
for (const auto& position : int16Raster2D.domain()) {
int16Raster2D[position] = position[0] + position[1];
}
Fits::VecRaster<std::int32_t, 3> int32Raster3D({16, 9, 3},
std::move(int32Vec));
auto int64Raster4D = Fits::Test::RandomRaster<std::int64_t, 4>({17, 9, 3, 24});
return {int16Raster2D, int32Raster3D, int64Raster4D};
}
TutoColumns createColumns() {
logger.info(" Creating columns...");
Fits::VecColumn<std::string> stringColumn({"STRING", "unit", 3}, 100);
for (long i = 0; i < stringColumn.rowCount(); ++i) {
}
Fits::VecColumn<std::int32_t> int32Column({
"INT32",
"", 1},
std::move(int32Vec));
auto float32Column = Fits::Test::RandomVectorColumn<float>(8, 100);
return {stringColumn, int32Column, float32Column};
}
logger.info("Creating a MEF file...");
Fits::MefFile f(filename, Fits::FileMode::Create);
const auto rasters = createRasters();
logger.info(" Writing image HDUs...");
const auto& image1 = f.assignImageExt("IMAGE1", rasters.int32Raster3D);
const auto& image2 = f.initImageExt<
std::int16_t>(
"IMAGE2", rasters.int16Raster2D.shape());
image2.raster().write(rasters.int16Raster2D);
const auto columns = createColumns();
logger.info(" Writing binary table HDUs...");
const auto& table1 = f.assignBintableExt("TABLE1", columns.stringColumn, columns.int32Column, columns.float32Column);
const auto& table2 = f.initBintableExt(
"TABLE2",
columns.stringColumn.info(),
columns.int32Column.info(),
columns.float32Column.info());
table2.columns().write(columns.stringColumn);
table2.columns().writeSeq(columns.int32Column, columns.float32Column);
writeRecords(f.primary().header());
(void)image1;
(void)table1;
}
void writeRecords(const Fits::Header& h) {
const auto records = createRecords();
logger.info(" Writing records...");
h.write(records.stringRecord);
h.writeSeq(records.intRecord, records.floatRecord, records.complexRecord);
h.writeSeq<Fits::RecordMode::UpdateExisting>(
Fits::Record<int>("INT", 1),
Fits::Record<float>("FLOAT", 3.14159F, "", "A larger piece of Pi"),
Fits::Record<std::complex<double>>("COMPLEX", {180., 90.}));
}
logger.info("Reading the MEF file...");
Fits::MefFile f(filename, Fits::FileMode::Read);
logger.info(" Accessing HDUs...");
const auto& primary = f.primary();
const auto primaryIndex = primary.index();
const auto& image2 = f.access<Fits::ImageHdu>(2);
const auto imageName = image2.readName();
const auto& table1 = f.find<Fits::BintableHdu>("TABLE1");
const auto tableIndex = table1.index();
logger.info() << " Primary index: " << primaryIndex;
logger.info() << " Name of the second extension: " << imageName;
logger.info() << " Index of the 'TABLE1' extension: " << tableIndex;
readRecords(primary.header());
readRaster(image2.raster());
readColumns(table1.columns());
}
void readRecords(const Fits::Header& h) {
logger.info(" Reading records...");
const auto intRecord = h.parse<int>("INT");
const int intValue = h.parse<int>("INT");
const auto someRecords = h.parseSeq(
Fits::as<std::string>("STRING"),
Fits::as<int>("INT"),
Fits::as<float>("FLOAT"),
Fits::as<std::complex<double>>("COMPLEX"));
const auto& thirdRecord = std::get<2>(someRecords);
const auto variantRecords = h.parseSeq<>({"INT", "COMPLEX"});
const auto tutoRecords = h.parseStruct<TutoRecords>(
Fits::as<std::string>("STRING"),
Fits::as<int>("INT"),
Fits::as<float>("FLOAT"),
Fits::as<std::complex<double>>("COMPLEX"));
const auto& stringRecord = tutoRecords.stringRecord;
logger.info() << " " << intRecord.keyword << " = " << intRecord.value << " " << intRecord.unit;
logger.info() << " INT value: " << intValue;
logger.info() << " " << thirdRecord.keyword << " = " << thirdRecord.value << " " << thirdRecord.unit;
logger.info() << " " << complexRecord.keyword << " = " << complexRecord.value.real() << " + "
<< complexRecord.value.imag() << "j " << complexRecord.unit;
logger.info() << " " << stringRecord.keyword << " = " << stringRecord.value << " " << stringRecord.unit;
}
void readRaster(const Fits::ImageRaster& du) {
logger.info(" Reading a raster...");
const auto& firstPixel = image[{0, 0}];
const auto& lastPixel = image.at({-1, -1});
logger.info() << " First pixel: " << firstPixel;
logger.info() << " Last pixel: " << lastPixel;
}
void readColumns(const Fits::BintableColumns& du) {
logger.info(" Reading columns...");
const auto vectorColumn = du.read<double>("VECTOR");
const auto byName = du.readSeq(Fits::as<std::string>("STRING"), Fits::as<std::int32_t>("INT32"));
const auto& stringColumn = std::get<0>(byName);
const auto byIndex = du.readSeq(Fits::as<std::string>(0), Fits::as<std::int32_t>(1));
const auto& intColumn = std::get<1>(byIndex);
const auto& firstString = stringColumn(0);
const auto& firstInt = intColumn(0);
const auto& lastFloat = vectorColumn.at(-1, -1);
logger.info() << " First string: " << firstString;
logger.info() << " First int: " << firstInt;
logger.info() << " Last float: " << lastFloat;
}
class EleFitsTutorial : public Elements::Program {
public:
auto options = Fits::ProgramOptions::fromAuxFile("Tutorial.txt");
options.positional("output", value<std::string>()->default_value("/tmp/tuto.fits"), "Output file");
return options.asPair();
}
const auto filename = args[
"output"].as<
std::string>();
logger.info() << "---";
logger.info() << "Hello, EleFits " << Fits::version() << "!";
logger.info() << "---";
writeMefFile(filename);
logger.info() << "---";
readMefFile(filename);
logger.info() << "---";
logger.info() << "The end!";
logger.info() << "---";
return Elements::ExitCode::OK;
}
};
MAIN_FOR(EleFitsTutorial)