Commit b4f563eb authored by Thomas Almeida's avatar Thomas Almeida
Browse files

pipe_macro: Make IFOComboMap index with bits indicating which IFOs are being used

Previously IFOComboMap was indexed as [single detector, two detectors,
three detectors, ...]. This means that checking to see how many and
which detectors are in use can't be easily done without referring back
to the table, and any changes to the table can potentially break other
parts of the code.

This patch changes IFOComboMap to be indexed by powers of two. That
means that any index of (2^i - 1) is a single detector, indicated by
index into IFOMap. Now when using IFOComboMap, the number of detectors
in use can be determined using `__builtin_popcount(icombo + 1)`, and
whether a single detector is in use can be done with the check `index &
(icombo + 1)`.
parent c023b1f0
......@@ -39,38 +39,34 @@
#define EPSILON 1e-6
int scan_trigger_ifos(int icombo, PostcohInspiralTable *trigger) {
int cur_ifo = 0, one_ifo_size = sizeof(char) * IFO_LEN;
int nifo = 0, one_ifo_size = sizeof(char) * IFO_LEN;
char final_ifos[MAX_ALLIFO_LEN];
gboolean pass_test = TRUE;
if ((icombo == 6 || icombo == 3 || icombo == 4)) { // H1L1, H1V1 or H1L1V1
if (trigger->snglsnr_H > EPSILON) {
strncpy(final_ifos + IFO_LEN * cur_ifo, "H1", one_ifo_size);
cur_ifo++;
} else
pass_test = FALSE;
}
if ((icombo == 6 || icombo == 3 || icombo == 5)) { // H1L1, L1V1 or H1L1V1
if (trigger->snglsnr_L > EPSILON) {
strncpy(final_ifos + IFO_LEN * cur_ifo, "L1", one_ifo_size);
cur_ifo++;
} else
pass_test = FALSE;
}
if ((icombo == 6 || icombo == 4 || icombo == 5)) { // H1V1, L1V1 or H1L1V1
if (trigger->snglsnr_V > EPSILON) {
strncpy(final_ifos + IFO_LEN * cur_ifo, "V1", one_ifo_size);
cur_ifo++;
} else
pass_test = FALSE;
// [THA]: Because icombo is sum(1 << index) - 1, we should add one to it
// so that we don't need to add one in the loop.
++icombo;
for (int i = 0; i < MAX_NIFO; ++i) {
// [THA]: We can determine if the IFO at IFOMap[i] is in the icombo by
// checking if that power of two exists in the combo
if (icombo & (1 << i)) {
// [THA]: This is a check that the data from this IFO is actually
// valid. If it's not valid, the number will be very *very* small
if (*(&trigger->snglsnr_H + i) > EPSILON) {
strncpy(final_ifos + IFO_LEN * nifo, IFOMap[i].name,
one_ifo_size);
nifo++;
} else {
pass_test = FALSE;
}
}
}
if (pass_test != TRUE) {
strncpy(trigger->ifos, final_ifos, cur_ifo * sizeof(char) * IFO_LEN);
trigger->ifos[IFO_LEN * cur_ifo] = '\0';
strncpy(trigger->ifos, final_ifos, nifo * one_ifo_size);
trigger->ifos[IFO_LEN * nifo] = '\0';
return get_icombo(trigger->ifos);
} else
return icombo;
} else {
return icombo - 1;
}
}
int get_icombo(char *ifos) {
......
......@@ -223,6 +223,7 @@ static GstFlowReturn cohfar_accumbackground_chain(GstPad *pad,
int isingle, nifo;
for (; intable < intable_end; intable++) {
icombo = get_icombo(intable->ifos);
// The combination of IFOs is invalid
if (icombo < 0) {
LIGOTimeGPS ligo_time;
XLALINT8NSToGPS(&ligo_time, GST_BUFFER_TIMESTAMP(inbuf));
......@@ -245,7 +246,12 @@ static GstFlowReturn cohfar_accumbackground_chain(GstPad *pad,
outtable++;
} else {
/* increment livetime if participating nifo >= 2 */
if (icombo > 2) {
// If icombo is a power of two, then there is only one participating
// IFO, thus we can use the property of `(x & (x-1)) != 0` to
// determine if we have more than one IFO participating
//
// Note that this is inverted because icombo is sum(1 << index) - 1
if ((icombo + 1) & icombo) {
nifo = strlen(intable->ifos) / IFO_LEN;
/* add single detector stats */
get_write_ifo_mapping(IFOComboMap[icombo].name, nifo,
......
......@@ -667,16 +667,20 @@ static gboolean cuda_postcoh_sink_setcaps(GstPad *pad, GstCaps *caps) {
data = gst_pad_get_element_private(pad);
set_offset_per_nanosecond(data, postcoh->offset_per_nanosecond);
set_channels(data, postcoh->channels);
// FIXME: need to consider non-standard ifo indexing, like HV, need
// testing
// [THA]: Non-standard IFO indexing (e.g. VH) works because `get_icombo`
// doesn't care about the ordering of IFOs
strncpy(state->all_ifos + IFO_LEN * i, data->ifo_name,
sizeof(char) * IFO_LEN);
}
state->all_ifos[IFO_LEN * nifo] = '\0';
state->ifo_combo_idx = get_icombo(state->all_ifos);
// [THA]: This is the only place that ifo_combo_idx is used. Perhaps remove
// it later to save space?
state->ifo_combo_idx = get_icombo(state->all_ifos);
// [THA]: sizeof() only works for arrays that we've statically created, so
// we use strlen() to get the length of the combination name
/* overwrite all_ifos to be the same with the combo in the IFOComboMap */
strncpy(state->all_ifos, IFOComboMap[state->ifo_combo_idx].name,
sizeof(IFOComboMap[state->ifo_combo_idx].name));
strlen(IFOComboMap[state->ifo_combo_idx].name));
state->all_ifos[IFO_LEN * nifo] = '\0';
/* initialize input_ifo_mapping, snglsnr matrix, and peak_list */
......
......@@ -13,13 +13,16 @@ typedef struct _IFOType {
} IFOType;
static const IFOType IFOMap[MAX_NIFO] = {
{ "H1", 0 },
{ "L1", 1 },
{ "V1", 2 },
{ "H1", 0 }, // 1 << 0 = 1
{ "L1", 1 }, // 1 << 1 = 2
{ "V1", 2 }, // 1 << 2 = 4
};
#define MAX_IFO_COMBOS 7 // 2^3-1
// A combination is sum(1 << index) - 1
// This gives us some nice mathematical properties that we can use to check
// if an IFO exists in a given ComboMap
static const IFOType IFOComboMap[MAX_IFO_COMBOS] = {
{ "H1", 0 }, { "L1", 1 }, { "V1", 2 }, { "H1L1", 3 },
{ "H1", 0 }, { "L1", 1 }, { "H1L1", 2 }, { "V1", 3 },
{ "H1V1", 4 }, { "L1V1", 5 }, { "H1L1V1", 6 },
};
/* function given a random ifo, output the index in the IFOComboMap list,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment