1
0
Fork 0
mirror of https://github.com/gwm17/Mask.git synced 2025-04-07 00:48:51 -04:00
Mask/src/MaskFile.cpp

364 lines
9.5 KiB
C++

#include "MaskFile.h"
#include <iostream>
#include <iomanip>
#include <sstream>
/*
FORMAT
HEADER (contains rxntype & nuclei numbers & beam kinetic energy) (64 bits, 8 bytes)
NSAMPLES(32bit) RXNTYPE(32bit)
end HEADER
There are NSAMPLES * (number of saved nuclei) data in the file. The number of nuclei saved is related to the
RXNTYPE. All nuclei (target, projectile, ejectile, residual, break1, etc...) are saved. A datum is as follows:
DATUM (contains kinematic data for a nucleus) (384 bits, 48 bytes)
Z(32bit) A(32bit) DETECTFLAG(32bit) E(64bit) KE(64bit) P(64bit) THETA(64bit) PHI(64bit)
end DATUM
*/
namespace Mask {
MaskFile::MaskFile() :
file_type(MaskFile::FileType::none), filename(""), buffer_position(0), buffer_end(0), data_size(0), buffersize_bytes(0), file()
{
}
MaskFile::MaskFile(const std::string& name, MaskFile::FileType type) :
file_type(type), filename(name), buffer_position(0), buffer_end(0), data_size(0), buffersize_bytes(0), file()
{
Open(filename, type);
}
bool MaskFile::Open(const std::string& name, MaskFile::FileType type) {
if(IsOpen()) {
std::cerr<<"Attempted to open file that is already open!"<<std::endl;
return false;
}
if(type == FileType::read) {
file.open(name, std::ios::in);
buffer_position = 0;
} else if (type == FileType::write) {
file.open(name, std::ios::out | std::ios::trunc);
} else if (type == FileType::append) {
file.open(name, std::ios::out | std::ios::app);
} else {
std::cerr<<"Invalid FileType at MaskFile::Open()"<<std::endl;
return IsOpen();
}
return IsOpen();
}
void MaskFile::Close() {
//Final flush (if necessary)
if(buffer_position > 0 && buffer_position < buffersize_bytes && (file_type == FileType::write || file_type == FileType::append)) {
file.write(data_buffer.data(), buffer_position);
}
file.close();
}
void MaskFile::WriteHeader(RxnType rxn_type, int nsamples) {
m_rxn_type = rxn_type;
switch(rxn_type)
{
case RxnType::PureDecay :
{
data_size = 3 * ( 5 * double_size + 2 * int_size + bool_size);
break;
}
case RxnType::OneStepRxn :
{
data_size = 4 * ( 5 * double_size + 2 * int_size + bool_size);
break;
}
case RxnType::TwoStepRxn :
{
data_size = 6 * ( 5 * double_size + 2 * int_size + bool_size);
break;
}
case RxnType::ThreeStepRxn :
{
data_size = 8 * ( 5 * double_size + 2 * int_size + bool_size);
break;
}
case RxnType::None :
{
std::cerr<<"Invalid RxnType at MaskFile::WriteHeader!"<<std::endl;
return;
}
}
buffersize_bytes = buffersize * data_size; //buffersize_bytes = # of events * size of an event
data_buffer.resize(buffersize_bytes);
uint32_t type_value = GetIntFromRxnType(m_rxn_type);
file.write((char*) &nsamples, int_size);
file.write((char*) &type_value, int_size);
}
MaskFileHeader MaskFile::ReadHeader() {
MaskFileHeader header;
std::vector<char> temp_buffer(4);
file.read(temp_buffer.data(), 4);
header.nsamples = *(int*)(&temp_buffer[0]);
file.read(temp_buffer.data(), 4);
uint32_t type_value = *(uint32_t*)(&temp_buffer[0]);
m_rxn_type = GetRxnTypeFromInt(type_value);
switch(m_rxn_type)
{
case RxnType::PureDecay:
{
data_size = 3 * ( 5 * double_size + 2 * int_size + bool_size);
break;
}
case RxnType::OneStepRxn:
{
data_size = 4 * ( 5 * double_size + 2 * int_size + bool_size);
break;
}
case RxnType::TwoStepRxn:
{
data_size = 6 * ( 5 * double_size + 2 * int_size + bool_size);
break;
}
case RxnType::ThreeStepRxn:
{
data_size = 8 * ( 5 * double_size + 2 * int_size + bool_size);
break;
}
case RxnType::None:
{
std::cerr<<"Unexpected reaction type at MaskFile::ReadHeader (rxn type = "<<GetIntFromRxnType(m_rxn_type)<<")! Returning"<<std::endl;
return header;
}
}
buffersize_bytes = buffersize * data_size;//buffersize_bytes = size of a datum * # of events
header.rxn_type = m_rxn_type;
data_buffer.resize(buffersize_bytes);
return header;
}
void MaskFile::WriteData(const std::vector<Nucleus>& data) {
char* data_pointer;
double datum;
int number;
bool flag;
std::size_t j;
for(unsigned int i=0; i<data.size(); i++) {
number = data[i].GetZ();
data_pointer = (char*) &number;
for(j=0; j<int_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
number = data[i].GetA();
data_pointer = (char*) &number;
for(j=0; j<int_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
flag = data[i].IsDetected();
data_pointer = (char*) &flag;
for(j=0; j<bool_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data[i].GetE();
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data[i].GetKE();
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data[i].GetP();
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data[i].GetTheta();
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data[i].GetPhi();
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
}
//Flush the buffer when it is full, and reset the position.
if(buffer_position == buffersize_bytes) {
file.write(data_buffer.data(), data_buffer.size());
buffer_position = 0;
}
}
void MaskFile::WriteData(const MaskFileData& data) {
char* data_pointer;
double datum;
int number;
bool flag;
std::size_t j;
for(unsigned int i=0; i<data.Z.size(); i++) {
number = data.Z[i];
data_pointer = (char*) &number;
for(j=0; j<int_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
number = data.A[i];
data_pointer = (char*) &number;
for(j=0; j<int_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
flag = data.detect_flag[i];
data_pointer = (char*) &flag;
for(j=0; j<bool_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data.E[i];
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data.KE[i];
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data.p[i];
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data.theta[i];
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data.phi[i];
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
}
//Flush the buffer when it is full, and reset the position.
if(buffer_position == buffersize_bytes) {
file.write(data_buffer.data(), data_buffer.size());
buffer_position = 0;
}
}
/*
Read data from the buffer and submit it to the client side as a MaskFileData struct.
When file reaches the end of the file (no more data to read), an empty MaskFileData with
eof == true is sent out signaling that the file is finished.
Should be used like
Mask::MaskFile input(file, Mask::MaskFile::FileType::read);
Mask::MaskFileHeader header = input.ReadHeader();
Mask::MaskFileData data;
while(true) {
data = input.ReadData();
if(data.eof) break;
Do some stuff...
}
input.Close();
Good luck
*/
MaskFileData MaskFile::ReadData() {
MaskFileData data;
//Fill the buffer when needed, reset the positon, and find the end
if(buffer_position == data_buffer.size() || buffer_position == buffer_end) {
file.read(data_buffer.data(), buffersize_bytes);
buffer_position = 0;
buffer_end = file.gcount();
if(buffer_end == 0 && file.eof()) {
data.eof = true;
return data;
}
}
uint64_t local_end = buffer_position + data_size;
if(local_end > buffer_end) {
std::cerr<<"Attempting to read past end of file at MaskFile::ReadData! Returning empty"<<std::endl;
data.eof = true;
return data;
}
while(buffer_position < local_end) {
data.Z.push_back(*(int*)(&data_buffer[buffer_position]));
buffer_position += int_size;
data.A.push_back(*(int*)(&data_buffer[buffer_position]));
buffer_position += int_size;
data.detect_flag.push_back(*(bool*)(&data_buffer[buffer_position]));
buffer_position += bool_size;
data.E.push_back(*(double*)(&data_buffer[buffer_position]));
buffer_position += double_size;
data.KE.push_back(*(double*)(&data_buffer[buffer_position]));
buffer_position += double_size;
data.p.push_back(*(double*)(&data_buffer[buffer_position]));
buffer_position += double_size;
data.theta.push_back(*(double*)(&data_buffer[buffer_position]));
buffer_position += double_size;
data.phi.push_back(*(double*)(&data_buffer[buffer_position]));
buffer_position += double_size;
}
return data;
}
};