Skip to content

Commit

Permalink
Updates to dfmux library for compatibility with hidfmux IceBoard firm…
Browse files Browse the repository at this point in the history
…ware (#106)

* Configurable internal clock rate to ensure that the IceBoard sub-second counter can be converted to a proper timestamp
* IceBoard packets indexed by module and sub-module block
* Add `center_frequency` and `bandwidth` attributes to `BolometerProperties` objects, to differentiate between the actual mm-wave observing frequency of the resonator and the band into which channels would be binned during mapmaking.
  • Loading branch information
arahlin authored Jul 31, 2023
1 parent 479ab70 commit 31c56c6
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 38 deletions.
7 changes: 5 additions & 2 deletions calibration/include/calibration/BoloProperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ class BolometerProperties : public G3FrameObject
{
public:
BolometerProperties() : x_offset(NAN), y_offset(NAN), band(NAN),
pol_angle(NAN), pol_efficiency(NAN), coupling(Unknown) {}
center_frequency(NAN), bandwidth(NAN), pol_angle(NAN),
pol_efficiency(NAN), coupling(Unknown) {}
std::string Description() const;

std::string physical_name; /* e.g. D4.A2.3.Y */
Expand All @@ -23,6 +24,8 @@ class BolometerProperties : public G3FrameObject
double y_offset; /* and el */

double band; /* Standard frequency units */
double center_frequency;
double bandwidth;
double pol_angle; /* Standard angular units */
double pol_efficiency; /* 0-1 */

Expand All @@ -44,7 +47,7 @@ class BolometerProperties : public G3FrameObject
};

G3_POINTERS(BolometerProperties);
G3_SERIALIZABLE(BolometerProperties, 6);
G3_SERIALIZABLE(BolometerProperties, 7);

G3MAP_OF(std::string, BolometerProperties, BolometerPropertiesMap);

Expand Down
12 changes: 10 additions & 2 deletions calibration/src/BoloProperties.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ template <class A> void BolometerProperties::serialize(A &ar, unsigned v)
ar & make_nvp("pixel_type", pixel_type);
}

if (v > 6) {
ar & make_nvp("center_frequency", center_frequency);
ar & make_nvp("bandwidth", bandwidth);
}
}

std::string BolometerProperties::Description() const
Expand All @@ -63,7 +67,11 @@ PYBINDINGS("calibration") {
.def_readwrite("y_offset", &BolometerProperties::y_offset,
"Vertical pointing offset relative to boresight in angular units.")
.def_readwrite("band", &BolometerProperties::band,
"Center of detector observing band in frequency units")
"Nominal center of detector observing band in frequency units")
.def_readwrite("center_frequency", &BolometerProperties::center_frequency,
"Measured center of detector observing band in frequency units")
.def_readwrite("bandwidth", &BolometerProperties::bandwidth,
"Measured bandwidth of detector observing band in frequency units")
.def_readwrite("pol_angle", &BolometerProperties::pol_angle,
"Polarization angle in angular units")
.def_readwrite("pol_efficiency", &BolometerProperties::pol_efficiency,
Expand All @@ -72,7 +80,7 @@ PYBINDINGS("calibration") {
"Optical coupling type")

.def_readwrite("wafer_id", &BolometerProperties::wafer_id,
"Name of the name this detector is on")
"Name of the wafer this detector is on")
.def_readwrite("pixel_id", &BolometerProperties::pixel_id,
"Name of the pixel of which this detector is a part")
.def_readwrite("pixel_type", &BolometerProperties::pixel_type,
Expand Down
6 changes: 4 additions & 2 deletions dfmux/include/dfmux/DfMuxBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
*/
struct DfMuxBoardSamples : public G3FrameObject, public std::map<int32_t, DfMuxSamplePtr> {
size_t nmodules; // Total number of modules expected from this board
size_t nblocks; // Total number of sub-module blocks expected from this board
size_t nchannels; // Total number of channels per block expected from this board

bool Complete() const { return (size() == nmodules); };
bool Complete() const { return (size() == nmodules * nblocks); };
template <class A> void serialize(A &ar, unsigned v);
};

G3_POINTERS(DfMuxBoardSamples);
G3_SERIALIZABLE(DfMuxBoardSamples, 1);
G3_SERIALIZABLE(DfMuxBoardSamples, 2);

/*
* DfMuxMetaSample: collection of DfMuxBoardSamples, indexed by board serial
Expand Down
11 changes: 10 additions & 1 deletion dfmux/include/dfmux/DfMuxCollector.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ class DfMuxSamplePacket : public G3FrameObject {
public:
int32_t board; /* Board serial number */
int32_t module; /* Module number (0-7) */
int32_t nmodules; /* Total number of modules on board (8) */
int32_t block; /* Sub-module block number (0-7 for hidfmux, 0 for dfmux) */
int32_t nmodules; /* Total number of modules on board (8 for dfmux) */
int32_t nblocks; /* Total number of blocks per module (8 for hidfmux, 1 for dfmux) */
int32_t nchannels; /* Total number of channels per block (128) */
DfMuxSamplePtr sample; /* Pointer to the DfMuxSample */
};

Expand Down Expand Up @@ -50,6 +53,10 @@ class DfMuxCollector {
int Start(); // Start listening thread
int Stop(); // Stop listening thread

// Configure iceboard clock rate (defaults to 100 MHz)
void SetClockRate(double rate);
double GetClockRate() { return clock_rate_; };

private:
int SetupUDPSocket(const char *listenaddr);
int SetupSCTPSocket(std::vector<std::string> hosts);
Expand All @@ -67,6 +74,8 @@ class DfMuxCollector {
std::vector<int32_t> board_list_;
int fd_;
in_addr_t listenaddr_;
double clock_rate_;
double clock_scale_;

SET_LOGGER("DfMuxCollector");
};
Expand Down
23 changes: 19 additions & 4 deletions dfmux/src/DfMuxBuilder.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ template <class A> void DfMuxBoardSamples::serialize(A &ar, const unsigned v)
ar & make_nvp("G3FrameObject", base_class<G3FrameObject>(this));
ar & make_nvp("samples", base_class<std::map<int, DfMuxSamplePtr> >(this));
ar & make_nvp("nmodules", nmodules);

if (v > 1) {
ar & make_nvp("nblocks", nblocks);
ar & make_nvp("nchannels", nchannels);
} else {
nblocks = 1;
nchannels = 128;
}
}

G3_SERIALIZABLE_CODE(DfMuxBoardSamples);
Expand Down Expand Up @@ -124,10 +132,13 @@ void DfMuxBuilder::ProcessNewData()
}

// Add to meta sample
g3_assert((*sample->sample)[pkt->board].find(pkt->module) ==
int idx = pkt->module * pkt->nblocks + pkt->block;
g3_assert((*sample->sample)[pkt->board].find(idx) ==
(*sample->sample)[pkt->board].end());
(*sample->sample)[pkt->board][pkt->module] = pkt->sample;
(*sample->sample)[pkt->board][idx] = pkt->sample;
(*sample->sample)[pkt->board].nmodules = pkt->nmodules;
(*sample->sample)[pkt->board].nblocks = pkt->nblocks;
(*sample->sample)[pkt->board].nchannels = pkt->nchannels;

while (oqueue_.size() > 0 && oqueue_.front().sample->size() ==
nboards_) {
Expand Down Expand Up @@ -203,12 +214,16 @@ PYBINDINGS("dfmux")
class_<DfMuxBoardSamples, bases<G3FrameObject>,
DfMuxBoardSamplesPtr>("DfMuxBoardSamples",
"Container structure for samples from modules on one board, mapping "
"0-indexed module IDs to a dfmux.DfMuxSample.")
"0-indexed module and block IDs to a dfmux.DfMuxSample.")
.def(std_map_indexing_suite<DfMuxBoardSamples, true>())
.def_readwrite("nmodules", &DfMuxBoardSamples::nmodules,
"Number of modules expected to report from this board")
.def_readwrite("nblocks", &DfMuxBoardSamples::nblocks,
"Number of sub-module blocks expected to report from this board")
.def_readwrite("nchannels", &DfMuxBoardSamples::nchannels,
"Number of channels per block expected to report from this board")
.def("Complete", &DfMuxBoardSamples::Complete,
"True if this structure contains data from all expected modules")
"True if this structure contains data from all expected modules and blocks")
.def_pickle(g3frameobject_picklesuite<DfMuxBoardSamples>())
;
register_pointer_conversions<DfMuxBoardSamples>();
Expand Down
24 changes: 17 additions & 7 deletions dfmux/src/DfMuxCollator.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -141,24 +141,34 @@ void DfMuxCollator::Process(G3FramePtr frame, std::deque<G3FramePtr> &out)
if (board == metasamp->end())
continue;

auto module = board->second.find(chan->mapping->module);
int mod_idx, chan_idx;
// slight hackery for indexing timepoint frames with modules split into blocks (e.g. with hidfmux)
if (board->second.nblocks != 1) {
mod_idx = chan->mapping->module * board->second.nblocks + (int)(chan->mapping->channel / board->second.nchannels);
chan_idx = chan->mapping->channel % board->second.nchannels;
} else {
mod_idx = chan->mapping->module;
chan_idx = chan->mapping->channel;
}

auto module = board->second.find(mod_idx);
if (module == board->second.end())
continue;

if (module->second->size()/2 <
size_t(chan->mapping->channel)) {
log_fatal("Board %d, module %d only has %zd "
size_t(chan_idx)) {
log_fatal("Board %d, module block %d only has %zd "
"channels, but trying to read %d",
chan->mapping->board_serial,
chan->mapping->module,
mod_idx,
module->second->size()/2,
chan->mapping->channel);
chan_idx);
}

(*chan->i)[sample] =
(*module->second)[chan->mapping->channel*2];
(*module->second)[chan_idx*2];
(*chan->q)[sample] =
(*module->second)[chan->mapping->channel*2 + 1];
(*module->second)[chan_idx*2 + 1];
}

// Next run through aux data. Missing points get filled in
Expand Down
Loading

0 comments on commit 31c56c6

Please sign in to comment.