Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overhaul October 2024 #35

Open
wants to merge 35 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d242a54
Clarify event partitioning modes and only check / create window defin…
trisyoungs Mar 12, 2024
bd188b4
Window arguments are now optional.
trisyoungs Mar 12, 2024
2cb203e
Keep all window options together.
trisyoungs Mar 12, 2024
70c5651
Create DumpEvents option.
trisyoungs Mar 12, 2024
eb43209
Rename function, adjust output text.
trisyoungs Mar 12, 2024
8443bdf
Rename event partitioning functions.
trisyoungs Mar 12, 2024
e55e095
Adding --dump-histogram option.
trisyoungs Oct 15, 2024
24481d0
Add missing source file.
trisyoungs Oct 15, 2024
e40ab28
Dump histogram working. Separate array creation and monitor loading.
trisyoungs Oct 15, 2024
629c01e
Rename to dump-detector.
trisyoungs Oct 15, 2024
2333d7d
Add --dump-monitor.
trisyoungs Oct 15, 2024
d4c3dd6
Rename some variables for clarity, and index monitors and detectors f…
trisyoungs Oct 15, 2024
216d170
Another variable rename.
trisyoungs Oct 15, 2024
1352c83
Reorder logic.
trisyoungs Oct 16, 2024
b5b5a4d
Dump events to file rather than stdout.
trisyoungs Oct 16, 2024
c9fb32d
Always load in times. Add loadBasicData() function.
trisyoungs Oct 16, 2024
68ae7a5
Simplify ctor, always load goodframes in basic data.
trisyoungs Oct 16, 2024
f21d366
Use at() to access array, fix output messages.
trisyoungs Oct 16, 2024
51ee8c0
Remove old files.
trisyoungs Oct 16, 2024
9c98d42
Capitalisation.
trisyoungs Oct 16, 2024
91d61ca
Process function capitalisation.
trisyoungs Oct 16, 2024
0e15ef7
Display basic info on files if no processing mode is selected.
trisyoungs Oct 16, 2024
278eaf4
Rename var, load and display run title.
trisyoungs Oct 16, 2024
053e663
Clarify output.
trisyoungs Oct 16, 2024
d2b91fe
Clarify header.
trisyoungs Oct 17, 2024
6e5be14
Add print events.
trisyoungs Oct 17, 2024
566c646
Clarify start time input arguments.
trisyoungs Oct 21, 2024
29da49e
Proper handling of data copying and file templating.
trisyoungs Oct 21, 2024
8efa216
Adjust output verbosity.
trisyoungs Oct 21, 2024
78ecddb
Don't forget to load monitor counts when preparing slices.
trisyoungs Oct 21, 2024
5e7bdd5
Willingly break system packages on the Mac.
trisyoungs Oct 21, 2024
303c4db
Don't hardcode gsl path.
trisyoungs Oct 21, 2024
a065882
No need for a Fortran compiler.
trisyoungs Oct 21, 2024
7dad384
Add GSL include dirs to search path.
trisyoungs Oct 21, 2024
d4a648d
Const?
trisyoungs Oct 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .github/workflows/build/osx/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ runs:
- name: Install Python Dependencies
shell: bash
run: |
pip3 install --user conan==1.*
pip3 install --user conan==1.* --break-system-packages

- name: Download HDF5 Artifacts
shell: bash
Expand All @@ -29,11 +29,10 @@ runs:
set -ex
export PATH="$(python3 -m site --user-base)/bin:$PATH"
HDF5_DIR="$(pwd)/${{ env.hdf5tag }}"
GSL_DIR="/usr/local/Cellar/gsl/2.7.1"
mkdir build && cd build

conan install ../
cmake ../ -G Ninja -DCMAKE_Fortran_COMPILER:string="gfortran-11" -DLOCAL_STATIC_HDF5:bool=true -DHDF5_DIR:path=${HDF5_DIR} -DLOCAL_STATIC_GSL:bool=true -DGSL_DIR:path=${GSL_DIR}
cmake ../ -G Ninja -DLOCAL_STATIC_HDF5:bool=true -DHDF5_DIR:path=${HDF5_DIR}
ninja

- name: Create Zip
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ if(LOCAL_STATIC_GSL)
else(LOCAL_STATIC_GSL)
find_package(GSL REQUIRED)
list(APPEND LINK_LIBS "${GSL_LIBRARIES}")
include_directories("${GSL_INCLUDE_DIRS}")
endif(LOCAL_STATIC_GSL)

option(
Expand Down
188 changes: 126 additions & 62 deletions np.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,64 +27,114 @@ int main(int argc, char **argv)
// Number of slices to partition window in to
int windowSlices_{1};
// Target spectrum for event get (optional)
std::optional<int> spectrumId_;
int targetIndex_;

// Define and parse CLI arguments
CLI::App app("NeXuS Processor (np), Copyright (C) 2024 Jared Swift and Tristan Youngs.");
// -- Window Definition
app.add_option("-n,--name", windowName_, "Name of the window, used as a prefix to all output files")
->group("Window Definition")
->required();
->group("Window Definition");
app.add_option("-s,--start", windowStartTime_,
"Start time of the window (relative to first input file start time unless --absolute-start is given)")
"Absolute start time of the window (i.e. seconds since epoch). Specify --relative-time if using a time "
"relative to the run start.")
->group("Window Definition");
app.add_option("-w,--width", windowWidth_, "Window width in seconds)")->group("Window Definition")->required();
app.add_flag(
"--relative-start", relativeStartTime_,
"Flag that the given window start time is relative to the first run start time, not absolute (seconds since epoch)")
app.add_option("-w,--width", windowWidth_, "Window width in seconds)")->group("Window Definition");
app.add_flag("--relative-start", relativeStartTime_,
"Flag that the given window start time is relative to the first run start time rather than absolute (seconds "
"since epoch)")
->group("Window Definition");
app.add_option("-d,--delta", windowDelta_, "Time between window occurrences, in seconds")
->group("Window Definition")
->required();
app.add_option("-d,--delta", windowDelta_, "Time between window occurrences, in seconds")->group("Window Definition");
app.add_option("--offset", windowOffset_, "Time after start time, in seconds, that the window begins.")
->group("Window Definition");
app.add_option("-l,--slices", windowSlices_, "Number of slices to split window definition in to (default = 1, no slicing)")
->group("Window Definition");
// -- Input Files
app.add_option("-f,--files", inputFiles_, "List of NeXuS files to process")->group("Input Files")->required();
// -- Output Files
app.add_option("--output-dir", outputDirectory_, "Output directory for generated NeXuS files.")->group("Output Files");
// -- Pre Processing
app.add_option("-g,--get", spectrumId_, "Get all events from specified spectrum index")->group("Pre-Processing");
// -- Processing Modes
app.add_option_function<int>(
"--dump-events",
[&](int id)
{
if (processingMode_ != Processors::ProcessingMode::None)
{
fmt::print("Error: Multiple processing modes given.\n");
throw(CLI::RuntimeError());
}
processingMode_ = Processors::ProcessingMode::DumpEvents;
targetIndex_ = id;
},
"Dump all events for specified detector index")
->group("Processing");
app.add_option_function<int>(
"--print-events",
[&](int id)
{
if (processingMode_ != Processors::ProcessingMode::None)
{
fmt::print("Error: Multiple processing modes given.\n");
throw(CLI::RuntimeError());
}
processingMode_ = Processors::ProcessingMode::PrintEvents;
targetIndex_ = id;
},
"Print all events for specified detector index")
->group("Processing");
app.add_option_function<int>(
"--dump-detector",
[&](int id)
{
if (processingMode_ != Processors::ProcessingMode::None)
{
fmt::print("Error: Multiple processing modes given.\n");
throw(CLI::RuntimeError());
}
processingMode_ = Processors::ProcessingMode::DumpDetector;
targetIndex_ = id;
},
"Dump specified detector histogram")
->group("Processing");
app.add_option_function<int>(
"--dump-monitor",
[&](int id)
{
if (processingMode_ != Processors::ProcessingMode::None)
{
fmt::print("Error: Multiple processing modes given.\n");
throw(CLI::RuntimeError());
}
processingMode_ = Processors::ProcessingMode::DumpMonitor;
targetIndex_ = id;
},
"Dump specified monitor histogram")
->group("Processing");
app.add_flag_callback(
"--summed",
[&]()
{
if (processingMode_ == Processors::ProcessingMode::None)
processingMode_ = Processors::ProcessingMode::Summed;
else
if (processingMode_ != Processors::ProcessingMode::None)
{
fmt::print("Error: Multiple processing modes given.\n");
throw(CLI::RuntimeError());
}
processingMode_ = Processors::ProcessingMode::PartitionEventsSummed;
},
"Sum windows / slices over all files and output NeXuS files per-slice")
->group("Processing");
app.add_flag_callback(
"--individual",
[&]()
{
if (processingMode_ == Processors::ProcessingMode::None)
processingMode_ = Processors::ProcessingMode::Individual;
else
if (processingMode_ != Processors::ProcessingMode::None)
{
fmt::print("Error: Multiple processing modes given.\n");
throw(CLI::RuntimeError());
}
processingMode_ = Processors::ProcessingMode::PartitionEventsIndividual;
},
"Output NeXuS files for each window / slice")
->group("Processing");
app.add_option("-l,--slices", windowSlices_, "Number of slices to split window definition in to (default = 1, no slicing)")
->group("Processing");
// -- Post Processing
app.add_flag_callback(
"--scale-monitors", [&]() { Processors::postProcessingMode_ = Processors::PostProcessingMode::ScaleMonitors; },
Expand All @@ -97,53 +147,67 @@ int main(int argc, char **argv)

CLI11_PARSE(app, argc, argv);

// Sanity check
if ((windowWidth_ + windowOffset_) > windowDelta_)
{
fmt::print("Error: Window width (including any optional offset) is greater than window delta.\n");
return 1;
}
if (windowSlices_ < 1)
{
fmt::print("Error: Invalid number of window slices provided ({}).\n", windowSlices_);
return 1;
}

// Perform pre-processing if requested
if (spectrumId_)
{
Processors::getEvents(inputFiles_, *spectrumId_);
}

// Construct the master window definition
if (relativeStartTime_)
{
// Need to query first NeXuS file to get its start time
if (inputFiles_.empty())
{
fmt::print("Error: Need at least one input NeXuS file.");
return 1;
}
NeXuSFile firstFile(inputFiles_.front());
firstFile.loadTimes();
fmt::print("Window start time converted from relative to absolute time: {} => {} (= {} + {})\n", windowStartTime_,
windowStartTime_ + firstFile.startSinceEpoch(), firstFile.startSinceEpoch(), windowStartTime_);
windowStartTime_ += firstFile.startSinceEpoch();
}
Window window(windowName_, windowStartTime_ + windowOffset_, windowWidth_);
fmt::print("Window start time (including any offset) is {}.\n", window.startTime());

// Perform processing
switch (processingMode_)
{
case (Processors::ProcessingMode::None):
fmt::print("No processing mode specified. We are done.\n");
fmt::print("No processing mode specified. Basic data from files will be shown.\n");
for (const auto &file : inputFiles_)
{
NeXuSFile nxs(file, true);
nxs.prepareSpectraSpace(true);
}
break;
case (Processors::ProcessingMode::DumpEvents):
case (Processors::ProcessingMode::PrintEvents):
Processors::dumpEventTimesEpoch(inputFiles_, targetIndex_,
processingMode_ == Processors::ProcessingMode::PrintEvents);
break;
case (Processors::ProcessingMode::Individual):
Processors::processIndividual(inputFiles_, outputDirectory_, window, windowSlices_, windowDelta_);
case (Processors::ProcessingMode::DumpDetector):
Processors::dumpDetector(inputFiles_, targetIndex_);
break;
case (Processors::ProcessingMode::Summed):
Processors::processSummed(inputFiles_, outputDirectory_, window, windowSlices_, windowDelta_);
case (Processors::ProcessingMode::DumpMonitor):
Processors::dumpMonitor(inputFiles_, targetIndex_);
break;
case (Processors::ProcessingMode::PartitionEventsIndividual):
case (Processors::ProcessingMode::PartitionEventsSummed):
// Sanity check
if ((windowWidth_ + windowOffset_) > windowDelta_)
{
fmt::print("Error: Window width (including any optional offset) is greater than window delta.\n");
return 1;
}
if (windowSlices_ < 1)
{
fmt::print("Error: Invalid number of window slices provided ({}).\n", windowSlices_);
return 1;
}

// Construct the master window definition
if (relativeStartTime_)
{
// Need to query first NeXuS file to get its start time
if (inputFiles_.empty())
{
fmt::print("Error: Need at least one input NeXuS file.");
return 1;
}
NeXuSFile firstFile(inputFiles_.front());
fmt::print("Window start time converted from relative to absolute time: {} => {} (= {} + {})\n",
windowStartTime_, windowStartTime_ + firstFile.startSinceEpoch(), firstFile.startSinceEpoch(),
windowStartTime_);
windowStartTime_ += firstFile.startSinceEpoch();
}
fmt::print("Window start time (including any offset) is {}.\n", windowStartTime_ + windowOffset_);

if (processingMode_ == Processors::ProcessingMode::PartitionEventsIndividual)
Processors::partitionEventsIndividual(inputFiles_, outputDirectory_,
{windowName_, windowStartTime_ + windowOffset_, windowWidth_},
windowSlices_, windowDelta_);
else
Processors::partitionEventsSummed(inputFiles_, outputDirectory_,
{windowName_, windowStartTime_ + windowOffset_, windowWidth_}, windowSlices_,
windowDelta_);
break;
default:
throw(std::runtime_error("Unhandled processing mode.\n"));
Expand Down
15 changes: 9 additions & 6 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
add_library(nexusProcess
add_library(
nexusProcess
dumpDetector.cpp
dumpMonitor.cpp
getEvents.cpp
nexusFile.cpp
partitionEventsIndividual.cpp
partitionEventsSummed.cpp
processCommon.cpp
processIndividual.cpp
processSummed.cpp
window.cpp
nexusFile.h
processors.h
window.h
)
window.h)

target_include_directories(nexusProcess PRIVATE ${PROJECT_SOURCE_DIR}/src ${CONAN_INCLUDE_DIRS})
target_include_directories(nexusProcess PRIVATE ${PROJECT_SOURCE_DIR} / src
${CONAN_INCLUDE_DIRS})

if(CONAN)
target_link_libraries(nexusProcess PUBLIC CONAN_PKG::fmt)
Expand Down
39 changes: 39 additions & 0 deletions src/dumpDetector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "nexusFile.h"
#include "processors.h"
#include <fmt/core.h>
#include <fstream>

namespace Processors
{
void dumpDetector(const std::vector<std::string> &inputNeXusFiles, int detectorIndex)
{
/*
* Dump histograms for the specified detector index
*/

fmt::print("Dumping histogram for detector index {}...\n", detectorIndex);

// Loop over input NeXuS files
for (auto &nxsFileName : inputNeXusFiles)
{
// Open the NeXuS file and load in detector counts
NeXuSFile nxs(nxsFileName);
nxs.prepareSpectraSpace();
nxs.loadDetectorCounts();

const auto spectrumId = nxs.spectrumForDetector(detectorIndex);

// Open the output file
std::ofstream output(fmt::format("{}.det.{}", nxsFileName, detectorIndex).c_str());
output << fmt::format("# TCB/us Counts [detector index {}, spectrum index = {}]\n", detectorIndex, spectrumId);
auto bin = 0;
const auto &counts = nxs.detectorCounts().at(spectrumId);
for (auto tof : nxs.tofBoundaries())
{
output << fmt::format("{} {}\n", tof, counts[bin++]);
}
output.close();
}
}

} // namespace Processors
37 changes: 37 additions & 0 deletions src/dumpMonitor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include "nexusFile.h"
#include "processors.h"
#include <fmt/core.h>
#include <fstream>

namespace Processors
{
void dumpMonitor(const std::vector<std::string> &inputNeXusFiles, int monitorIndex)
{
/*
* Dump histograms for the specified monitor index
*/

fmt::print("Dumping histogram for monitor index {}...\n", monitorIndex);

// Loop over input NeXuS files
for (auto &nxsFileName : inputNeXusFiles)
{
// Open the NeXuS file and load in monitor counts
NeXuSFile nxs(nxsFileName);
nxs.prepareSpectraSpace();
nxs.loadMonitorCounts();

// Open the output file
std::ofstream output(fmt::format("{}.mon.{}", nxsFileName, monitorIndex).c_str());
output << "# TCB/us Counts\n";
auto bin = 0;
const auto &counts = nxs.monitorCounts().at(monitorIndex);
for (auto tof : nxs.tofBoundaries())
{
output << fmt::format("{} {}\n", tof, counts[bin++]);
}
output.close();
}
}

} // namespace Processors
Loading
Loading