Public Member Functions | Public Attributes | List of all members
GlobalTrigger Class Reference

Global Trigger. More...

#include <GlobalTrigger.h>

Public Member Functions

 GlobalTrigger (Settings *settings1, Anita *anita1)
 
void GetArrivalTimes (int inu, Anita *anita1, const Vector &rf_direction)
 
void PassesTrigger (Settings *settings1, Anita *anita1, int discones_passing, int mode, int *l3trig, int l2trig[Anita::NPOL][Anita::NTRIGGERLAYERS_MAX], int l1trig[Anita::NPOL][Anita::NTRIGGERLAYERS_MAX], int antennaclump, int loctrig[Anita::NPOL][Anita::NLAYERS_MAX][Anita::NPHI_MAX], int loctrig_nadironly[Anita::NPOL][Anita::NPHI_MAX], int inu, int *thispasses, bool noiseOnly=false)
 Evaluate the full trigger simulation for a given payload configuration. More...
 
void PassesTrigger (Settings *settings1, Anita *anita1, int discones_passing, int mode, int *l3trig, int l2trig[Anita::NPOL][Anita::NTRIGGERLAYERS_MAX], int l1trig[Anita::NPOL][Anita::NTRIGGERLAYERS_MAX], int antennaclump, int loctrig[Anita::NPOL][Anita::NLAYERS_MAX][Anita::NPHI_MAX], int loctrig_nadironly[Anita::NPOL][Anita::NPHI_MAX], int inu, double this_threshold, int *thispasses, bool noiseOnly=false)
 
void PassesTriggerBasic (Settings *settings1, Anita *anita1, int discones_passing, int mode, int *l3trig, int l2trig[Anita::NPOL][Anita::NTRIGGERLAYERS_MAX], int l1trig[Anita::NPOL][Anita::NTRIGGERLAYERS_MAX], int antennaclump, int loctrig[Anita::NPOL][Anita::NLAYERS_MAX][Anita::NPHI_MAX], int loctrig_nadironly[Anita::NPOL][Anita::NPHI_MAX], int *thispasses, int inu, bool noiseOnly=false)
 
void PassesTriggerCoherentSum (Settings *settings1, Anita *anita1, int inu, int *thispasses)
 
void PassesTriggerSummedPower (Settings *settings1, Anita *anita1)
 
void PassesTriggerScheme5 (Anita *anita1, double this_threshold, int *thispasses)
 
void L3Trigger (Settings *settings1, Anita *anita1, int loctrig[Anita::NPOL][Anita::NLAYERS_MAX][Anita::NPHI_MAX], int loctrig_nadironly[Anita::NPOL][Anita::NPHI_MAX], int discones_passing, int *l3trigy, int *thispasses)
 Level 3 Trigger Function. More...
 
int GetPhiSector (Settings *settings1, int i, int j)
 Provides a mapping between the 4 layers and 16 phi sectors physically to the 3 layers and 16 sectors logically. More...
 
void GetAnitaLayerPhiSector (Settings *settings1, int i, int j, int &whichlayer, int &whichphisector)
 Provides a mapping between the 4 layers and 16 phi sectors physically to the 3 layers and 16 sectors logically. More...
 
void FillInNadir (Anita *anita1, int *ant)
 Virtual nadir antennas had effective L2 triggers based on neighbor antennas. More...
 
void FillInNadir (Settings *settings1, Anita *anita1, int ant)
 Virtual nadir antennas had effective L2 triggers based on neighbor antennas. More...
 
double three_bit_round (double input, bool round_zero_up=true, bool allow_zero=false)
 Three bit rounding function. More...
 
void convert_wfm_to_3_bit (const vector< double > &wfm, double rms, vector< double > &output)
 Converts a waveform by sampling it into 3 bits, after it is normalized to the RMS.
 
void delay_align_antenna_waveforms (const vector< vector< vector< double > > > &waveforms, const vector< vector< unsigned int > > &delays, vector< vector< double > > &output)
 Calculate the difference in each arrival time due to propagation delay of the signal. More...
 
void sum_aligned_waveforms (const vector< vector< double > > &waveforms, vector< double > &output)
 Given a number of waveforms (usually 3) which are delay-aligned, it sums them. More...
 
void square_waveform_elements (const vector< double > &waveform, vector< double > &output)
 Performs an element-wise squaring of the values of the input array. More...
 
double summed_power_window (const vector< double > &waveform, unsigned int start_index, unsigned int length)
 Sum a window from the specified starting index. More...
 
int findahit (vector< int > myvector, int first, int last)
 
int findanl3 (int *l3, int NPHISECTORS)
 
int L1Anita3_OnePhiSector (int IZERO, vector< int > &vl0_realtime_bottom, vector< int > &vl0_realtime_middle, vector< int > &vl0_realtime_top, vector< int > &vl1_realtime_bottom, vector< int > &vl1_realtime_middle, vector< int > &vl1_realtime_top)
 
void L1Anita3_AllPhiSectors (Anita *anita1, std::array< std::array< std::vector< int >, 16 >, 2 > &l1trig)
 
int L1Anita4_OnePhiSector (int IZERO, vector< int > &vl0_realtime_bottom, vector< int > &vl0_realtime_middle, vector< int > &vl0_realtime_top, vector< int > &vl1_realtime_bottom, vector< int > &vl1_realtime_middle, vector< int > &vl1_realtime_top)
 
void L1Anita4_AllPhiSectors (Anita *anita1, std::array< std::array< std::vector< int >, 16 >, 2 > &l1trig)
 
void L2Anita3and4 (Anita *anita1, std::array< std::array< std::vector< int >, 16 >, 2 > l1trig, std::array< std::array< std::vector< int >, 16 >, 2 > &l2trig)
 
void L3Anita3and4 (Anita *anita1, std::array< std::array< std::vector< int >, 16 >, 2 > vl2trig, int vl3trig[2][16], int *thispasses)
 
int PartofL1Anita4LR_ScA_TwoPhiSectors (int ilayerreverse, int IZERO, int ipolar, vector< int > &v1l0_realtime_left, vector< int > &v2l0_realtime_left, vector< int > &v1l0_realtime_right, vector< int > &v2l0_realtime_right, vector< int > &vl1_realtime)
 
int L1Anita4LR_ScA_TwoPhiSectors (int IZERO, int ipolar, vector< int > &vl0_realtime_bottomleft, vector< int > &v2l0_realtime_bottomleft, vector< int > &vl0_realtime_bottomright, vector< int > &v2l0_realtime_bottomright, vector< int > &vl0_realtime_middleleft, vector< int > &v2l0_realtime_middleleft, vector< int > &vl0_realtime_middleright, vector< int > &v2l0_realtime_middleright, vector< int > &vl0_realtime_topleft, vector< int > &v2l0_realtime_topleft, vector< int > &vl0_realtime_topright, vector< int > &v2l0_realtime_topright, vector< int > &vl1_realtime_bottom, vector< int > &vl1_realtime_middle, vector< int > &vl1_realtime_top)
 
void L1Anita4LR_ScA_AllPhiSectors (Anita *anita1, std::array< std::array< std::vector< int >, 16 >, 2 > &vl1trig)
 
void L3Anita4LR_ScA (Anita *anita1, std::array< std::array< std::vector< int >, 16 >, 2 > vl2trig, int *thispasses)
 
void L1Anita4LR_ScB_AllAntennas_OneBin (int IZERO, Anita *anita1, std::array< std::array< vector< int >, 16 >, 3 > &vl1trig_anita4lr_scb, int &npassesl1)
 
void L1Anita4LR_ScB_OneBin (int IZERO, vector< int > vleft, vector< int > vright, vector< int > &vl1trig)
 
void L2Anita4LR_ScB_AllPhiSectors_OneBin (int IZERO, Anita *anita1, std::array< std::array< vector< int >, 16 >, 3 > vl1trig_anita4lr_scb, std::array< std::array< vector< int >, 3 >, 16 > &vl2_realtime_anita4_scb, int &npassesl2, int &npassesl2_type0)
 
void L2Anita4LR_ScB_OnePhiSector_OneBin (int IZERO, vector< int > vl1_bottom, vector< int > vl1_middle, vector< int > vl1_top, std::array< vector< int >, 3 > &vl2_realtime_anita4_scb, int &npassesl2, int &npassesl2_type0)
 
int L3or30Anita4LR_ScB_TwoPhiSectors_OneBin (int IZERO, std::array< vector< int >, 3 > vl2_realtime_anita4_scb, std::array< vector< int >, 3 > vl2_realtime_anita4_scb_other, int npass1, int npass2)
 
void L3Anita4LR_ScB_OneBin (int IZERO, Anita *anita1, std::array< std::array< vector< int >, 3 >, 16 > vl2_realtime_anita4_scb, std::array< vector< int >, 16 > &vl3trig_type0, std::array< vector< int >, 16 > &vl3trig_type1, int &thispasses_l3type0, int &thispasses_l3type1)
 
void delayL0 (vector< int > &vl0, double delay)
 
void delay_AllAntennas (Anita *anita1)
 

Public Attributes

double TRIGTIMESTEP
 
int nstepback
 
double L1_COINCIDENCE_ANITA3 [3]
 
double LASTTIMETOTESTL1_ANITA3
 
double L3_COINCIDENCE
 
double L1_COINCIDENCE_MOREGENERAL [3][2]
 
double LASTTIMETOTESTL1_ANITA4
 
double LASTTIMETOTESTL1_ANITA4LR_SCA
 
double L1_COINCIDENCE_LR_SCA [2]
 
double WHICHLAYERSLCPRCP [Anita::NTRIGGERLAYERS_MAX]
 
double L1_COINCIDENCE_ANITA4LR_SCB
 
double LASTTIMETOTESTL1_ANITA4LR_SCB
 
double L2_COINCIDENCE_ANITA4LR_SCB [3]
 
double LASTTIMETOTESTL2_ANITA4LR_SCB
 
double L3_COINCIDENCE_ANITA4LR_SCB
 
double DELAYS [3]
 
vector< int > flag_e_L1 [Anita::NPHI_MAX]
 
vector< int > flag_h_L1 [Anita::NPHI_MAX]
 
UShort_t phiTrigMask [Anita::NPOL]
 
UShort_t l1TrigMask [Anita::NPOL]
 
UShort_t thresholds_eachant [2][48]
 
double volts [2][Anita::NLAYERS_MAX][Anita::NPHI_MAX]
 
double volts_em [2][Anita::NLAYERS_MAX][Anita::NPHI_MAX]
 
double volts_original [2][Anita::NLAYERS_MAX][Anita::NPHI_MAX]
 
int nchannels_perrx_triggered [48]
 
int nchannels_perband_triggered [48][8]
 
int channels_passing [Anita::NLAYERS_MAX][Anita::NPHI_MAX][2][Anita::NBANDS_MAX]
 
int channels_passing_justNoise [Anita::NLAYERS_MAX][Anita::NPHI_MAX][2][Anita::NBANDS_MAX]
 
vector< int > vchannels_passing [Anita::NLAYERS_MAX][Anita::NPHI_MAX][2]
 
std::array< std::array< std::array< std::array< std::vector< int >, 5 >, 2 >, 16 >, 3 > arrayofhits
 
std::array< std::array< std::array< std::array< std::vector< int >, 5 >, 2 >, 16 >, 3 > arrayofhitsnoise
 
std::array< std::array< std::array< std::array< std::vector< int >, 5 >, 2 >, 16 >, 3 > arrayofhitsall
 
int triggerbits [Anita::NTRIG]
 
vector< vector< vector< double > > > volts_rx_rfcm_trigger
 
int first_phi_sector_hit
 

Detailed Description

Global Trigger.

Definition at line 12 of file GlobalTrigger.h.

Collaboration diagram for GlobalTrigger:
Collaboration graph
[legend]

Member Function Documentation

void GlobalTrigger::delay_align_antenna_waveforms ( const vector< vector< vector< double > > > &  waveforms,
const vector< vector< unsigned int > > &  delays,
vector< vector< double > > &  output 
)

Calculate the difference in each arrival time due to propagation delay of the signal.

Method void GetArrivalTimes: input: direction of rf propagation when it arrives at balloon (earth frame), balloon location (earth frame) rotation of balloon around axis of symmetry

output: array of doubles giving time at which rf reaches antenna feedpoint, where the first antenna is hit at t=0.

This method takes as input the rf direction, the location of the balloon, the phi spin of the balloon, and an array of vectors initialized to point to the location of the antennas, assuming the balloon is upright at the south pole, with no spin.

The method transforms the antenna location vectors to point from the current center of the balloon (actually the center of the top ring of antennas) to the antennas, assuming that the balloon is vertical over the surface of the ice, and taking into account a possible phi spin.

The method projects the antenna direction vector onto the rf direction to find the distance between the center of the balloon and each antenna, along the direction of rf propagation.

Finally, arrival times are shifted so that the first antenna triggered is at time 0.Shifts waveforms in time to simulate relative signal delays caused by propagation

This function accepts nested vectors of waveforms along with nested vectors of delays and then iterates through nested for-loops whose bounds iterate with the surrounding scope.

The output is assembled and then truncated to prevent uneven array lengths post-shifting.

Todo:
Instead of accepting nested vectors, boost::multi_array/_views or PayloadArray objects should be passed in and out.
    Something to keep in mind is that RVO (Return Value Optimization) can
    make it actually faster to return a large object by value if it can
    be used to immediately construct another object.

    Also, instead of worrying about resizing the arrays it'd probably
    be better to store the time index of the last signal bin, and then
    simply pass that bin as the end iterator offset for the truncated array.

    The use of vector<>::push_back may cause performance issues but more
    importantly the use of clear() and element-by-element assignment causes
    more concern than they're worth, so they should be replaced with
    std::copy() for the temporaries which need it and just use functions from
    the standard library's #include <algorithm>.

    Realistically though, the delays should just be used to advance the iterators.

Definition at line 1713 of file GlobalTrigger.cc.

void GlobalTrigger::FillInNadir ( Anita anita1,
int *  ant 
)

Virtual nadir antennas had effective L2 triggers based on neighbor antennas.

the nadir layer only has 8 antennas but there are 16 slots in the "trigger layer" ant[][] is 1 if the l1 trigger is fired for each antenna fill the slots in between the actual antennas with the "or" of the neighboring antennas

Todo:
Deprecate this function in favor of PayloadArray or boost::multi_array objects which provide the ability to have multiple indexing schemes for a given collection of objects. For this case specifically PayloadArray was designed to have iterators and accessors which "OR" the values of the neighboring antennas, and are optionally read-only.

Definition at line 1395 of file GlobalTrigger.cc.

void GlobalTrigger::FillInNadir ( Settings settings1,
Anita anita1,
int  ant 
)

Virtual nadir antennas had effective L2 triggers based on neighbor antennas.

the nadir layer only has 8 antennas but there are 16 slots in the "trigger layer" ant[][] is 1 if the l1 trigger is fired for each antenna fill the slots in between the actual antennas with the "or" of the neighboring antennas

Todo:
Deprecate this function in favor of PayloadArray or boost::multi_array objects which provide the ability to have multiple indexing schemes for a given collection of objects. For this case specifically PayloadArray was designed to have iterators and accessors which "OR" the values of the neighboring antennas, and are optionally read-only.

Definition at line 1352 of file GlobalTrigger.cc.

void GlobalTrigger::GetAnitaLayerPhiSector ( Settings settings1,
int  i,
int  j,
int &  whichlayer,
int &  whichphisector 
)

Provides a mapping between the 4 layers and 16 phi sectors physically to the 3 layers and 16 sectors logically.

Because every payload had a different number of antennas, this provides a relation from where the antennas were located physically and how they were considered to by positioned logically by the triggering system.

Todo:
Deprecate this function in favor of PayloadArray or boost::multi_array objects which provide the ability to have multiple indexing schemes for a given collection of objects.

Definition at line 1457 of file GlobalTrigger.cc.

int GlobalTrigger::GetPhiSector ( Settings settings1,
int  i,
int  j 
)

Provides a mapping between the 4 layers and 16 phi sectors physically to the 3 layers and 16 sectors logically.

Because the top two layers of antennas had only 8 antennas each and were rotated perfectly out of phase of one another, such a conversion was needed to keep the trigger sane.

Todo:
Deprecate this function in favor of PayloadArray or boost::multi_array objects which provide the ability to have multiple indexing schemes for a given collection of objects.

Definition at line 1426 of file GlobalTrigger.cc.

void GlobalTrigger::L3Trigger ( Settings settings1,
Anita anita1,
int  loctrig[Anita::NPOL][Anita::NLAYERS_MAX][Anita::NPHI_MAX],
int  loctrig_nadironly[Anita::NPOL][Anita::NPHI_MAX],
int  discones_passing,
int *  l3trig,
int *  thispasses 
)

Level 3 Trigger Function.

Given a trigger scheme (represented via the Settings::WHICH value), the results of the previous trigger (the L2 trigger) are compared against one of the various combinatoric triggers.

For Anita 2, the trigger required two layers out of the three L2 triggers in a phi sector, but for sectors which did not have a nadir antennas, these "phantom nadirs" were a boolean "OR" of the two nadir antennas closest to that phi sector. Finally, two neighboring phi sectors must have accomplished this in order to produce a triggered L3.

Todo:
The organization of this function needs to be changed so that a single variables turns on (or off) a single component of the trigger/simulation. The organization as it stands makes it difficult to know what features a particular trigger should be exhibiting.
    Along this topic, the values for settings should be either strings, values mapped
    to strings (such as boost::variable_map), or enumerations with a proper descriptive
    declared name. That way when settings1->WHICH would have a value of 9, it would be
    written settings1->WHICH==ANITA3.

    Lastly, the boolean functions which are chained together to represent the full state
    machine of the trigger electronics are an impossible-to-find bug waiting to happen.
    "Short circuit evaluation" and less-than-obvious operator fixity rules make the
    given representation one of the most difficult to manage.

    The use of standard library functions "all_of", "any_of", "none_of", "count", and
    "count_if" on an intelligent container like boost::multi_array or PayloadArray would
    make the expression of the trigger requirements much more clear and less prone to
    error.

    Finally, all modern compilers will automatically optimize power-of-two multiplication
    of integers into a bit shift, so nothing is lost by switching from explicit shifts to
    multiplication, and readability is gained.

Definition at line 1540 of file GlobalTrigger.cc.

void GlobalTrigger::PassesTrigger ( Settings settings1,
Anita anita1,
int  discones_passing,
int  mode,
int *  l3trig,
int  l2trig[Anita::NPOL][Anita::NTRIGGERLAYERS_MAX],
int  l1trig[Anita::NPOL][Anita::NTRIGGERLAYERS_MAX],
int  antennaclump,
int  loctrig[Anita::NPOL][Anita::NLAYERS_MAX][Anita::NPHI_MAX],
int  loctrig_nadironly[Anita::NPOL][Anita::NPHI_MAX],
int  inu,
int *  thispasses,
bool  noiseOnly = false 
)

Evaluate the full trigger simulation for a given payload configuration.

PassesTrigger handles the logistics for the triggering of all trigger systems.

The triggering system begins with the calculations to determine which channels will pass the "L0" trigger. Each antenna on Anita 2 had two polarizations, and each polarization was divided up into five frequency bands. The frequency bands would be independently measured to see if the signal was over the threshold. If 3 of the 8 bands for an antenna (in some experiments, at least) exceeded the threshold then that antenna would have triggered an "L1", or antenna-level trigger.

From there, the different triggering systems start to diverge, each requiring some different combinatoric trigger to be satisfied before escalating to the next-higher-level trigger.

The trigger system using TRIGGERSCHEME==3 is a good deal different from the other triggers, because of a few thing:

  • All bands were assumed to have passed
  • The trigger scans over many possible physical propagation delays in an attempt to find the highest power
  • If the highest power for that antenna group happens to exceed the set threshold, then...
  • If two neighboring phi sectors find powers above the threshold, then a global trigger occurs

The antenna trigger clusters have been different configurations in the past, with early Anita3 designs using the "Coherent Sum Trigger", which uses 9 antennas per cluster. More current trigger designs use 3 antennas per coherent-summing-group, though this more recent trigger is referred to as the "Summed Power Trigger"

Todo:
This function needs to be heavily refactored into either functions which perform some smaller part of every trigger, or some functions which perform one triggering system in its entirely, or a combination of the two.
    The longer a function gets, the less confidence can be had in it because instead of many small, well-tested
    modular functions, functions of this length develop into massive hacks which may appear to perform the same
    but no such guarantee can be made.

    There are a lot of functions and code snippets which could be very easily replaced by standard library
    functions, or by embracing "RAII" ("Resource Acquisition Is Initialization") and using fewer C arrays and
    more of the standard library functions (particularly those in "algorithm", "functional", and "numeric"
    and above all the container libraries. Those libraries will help (along with the refactor) alleviate the
    difficult-to-follow nesting of for-loops within conditional statements.

    Many of the combinatoric triggers can have a logical mask made in order to very clearly define and later
    comprehend the requirements of the triggers, and less nesting of loops is necessary.

    Using scoped accumulators for calculating statistics is also a good idea here, as it reduces the number of
    functions and the number of objects needed to produce a distribution of values to just one object, making
    mistakes/errors much less likely. *         

    There is a decent amount of dead code which should be pruned, as well.

Definition at line 211 of file GlobalTrigger.cc.

void GlobalTrigger::square_waveform_elements ( const vector< double > &  waveform,
vector< double > &  output 
)

Performs an element-wise squaring of the values of the input array.

Todo:
This function should be deprecated because the same functionality is provided by the standard library:
std::transform(wfm.begin(), wfm.end(), result.begin(), [](auto& x){x *= x});

    or by using the boost library:

result = boost::transform(wfm, [](auto& x){x *= x});

Definition at line 1778 of file GlobalTrigger.cc.

void GlobalTrigger::sum_aligned_waveforms ( const vector< vector< double > > &  waveforms,
vector< double > &  output 
)

Given a number of waveforms (usually 3) which are delay-aligned, it sums them.

Todo:
This should not take nested vectors as a parameter but rather a boost::multi_array or boost::multi_array_view, or an instance of the PayloadArray class, which is a multi_array container modified to have circular indices. Also, the bounds of the for-loop should not be separately declared as it just adds another point of failure.

Definition at line 1750 of file GlobalTrigger.cc.

double GlobalTrigger::summed_power_window ( const vector< double > &  waveform,
unsigned int  start_index,
unsigned int  length 
)

Sum a window from the specified starting index.

Todo:
This function should be replaced as it is unnecessary – the same thing can be done more legibly with std::accumulate(...) :
double sum = std::accumulate(wfm.begin(), wfm.end(), 0.); 

Definition at line 1795 of file GlobalTrigger.cc.

double GlobalTrigger::three_bit_round ( double  input,
bool  round_zero_up = true,
bool  allow_zero = false 
)

Three bit rounding function.

This function takes an input and digitizes it into one of 8 (2^3 == 8) intervals, with unit spacing from -3.5 to +3.5.

This function takes a number and will round it to the closest integer multiple plus 0.5, using randomness to get distribute exact integers.

Definition at line 1812 of file GlobalTrigger.cc.


The documentation for this class was generated from the following files: