https://wiki.gnuradio.org/api.php?action=feedcontributions&user=Kyle&feedformat=atomGNU Radio - User contributions [en]2024-03-29T05:37:52ZUser contributionsMediaWiki 1.39.5https://wiki.gnuradio.org/index.php?title=Logging&diff=13726Logging2024-01-02T17:35:21Z<p>Kyle: note about changing log level w/python</p>
<hr />
<div>[[Category:Usage Manual]]<br />
This page describes the logging system, as it is in GNU Radio 3.10 and later. For the logging as realized in earlier versions, see [[Legacy_Logging|Legacy Logging]].<br />
<br />
= Usage =<br />
<br />
'''Log what you think might be useful.''' Some fundamental change occurred that you think you'd like to know about later on? Log. An error occurred? Definitely log! A setter method got a value that looks strange, but it's not an error, while probably still worth investigating? Log!<br />
<br />
GNU Radio's logging system is very flexible and pretty fast. If you think it makes sense to be able to reconstruct what happened later on, that might be something you want to log (maybe with a low priority, see the section on Levels**.<br />
<br />
'''Never use standard output for logging.''' GNU Radio's logging system allows for anyone who has special logging needs (e.g. forward all log messages to a central log server, have logs in a graphical environment) to attach to it. Can't do that with <code>std::cout</code>, <code>std::cerror</code>, <code>printf</code>, or Python's <code>print</code>.<br />
<br />
== Log Message Categories / Levels ==<br />
<br />
The GNU Radio logging system is based on [https://github.com/gabime/spdlog spdlog] and hence exposes the same log levels. Use these to denote the severity of your logging message. For example, use <code>info</code> for things that might be interesting for someone observing the operation of your flow graph, use <code>warn</code> to notify that something ''might reasonably be assumed to be wrong'' and that they need to look into it, and <code>error</code> if something really is wrong and needs to be fixed.<br />
<br />
The log levels are ordered, so when you tell the logging system &quot;I don't care about anything less than a warning&quot;, you will not get <code>info</code> messages (and anything below in severity).<br />
<br />
The levels are:<br />
<br />
* <code>trace</code>: Tracing your code's operation. This is mostly for when you're developing an algorithm and need to log specific values that it calculates<br />
* <code>debug</code>: Used for debugging purposes, and should not be visible under usual usage.<br />
* <code>info</code>: Information that does not require immediate attention, but might be of interest to someone observing the operation<br />
* <code>warn</code>: A warning. Means something ''might'' be wrong and it's probably worth looking into it.<br />
* <code>error</code>: An error has occurred. Meaning something definitely is wrong.<br />
* <code>critical</code>: An error that cannot be recovered from. For all that concerns your block/functional unit, execution cannot continue sensibly.<br />
<br />
== Logging in Python ==<br />
<br />
In GNU Radio 3.10, you construct your own logger from <code>gr.logger</code>. For example, in a block context:<br />
<br />
<syntaxhighlight lang="python">import numpy as np<br />
from gnuradio import gr<br />
class my_block(gr.sync_block):<br />
def __init__(self, foo = 1, bar = False):<br />
gr.sync_block.__init__(<br />
self,<br />
name="My fancy block",<br />
in_sig=[np.float32],<br />
out_sig=[np.float32])<br />
self.foo = foo<br />
self.bar = bar<br />
self.my_log = gr.logger(self.alias())<br />
def work(self, input_items, output_ites):<br />
if max(input_items) > self.foo:<br />
self.my_log.warn(f"maximum of input {max(input_items)} larger than foo ({self.foo})")<br />
output_items[0][:] = input_items[0][:]<br />
return len(output_items[0])</syntaxhighlight><br />
or outside a block<br />
<br />
<syntaxhighlight lang="python">from gnuradio import gr<br />
…<br />
logging_mc_logface = gr.logger("prime searcher")<br />
…<br />
if number % potential_factor == 0:<br />
logging_mc_logface.info(f"{number} is not a prime, as it can be divided by {potential_factor}")<br />
return False</syntaxhighlight><br />
As you can see, we're using the fact that Python has [https://docs.python.org/3/reference/lexical_analysis.html#formatted-string-literals formatted string literals] (<code>f&quot;something {} more&quot;</code>) to embed values in log messages. The Python [https://docs.python.org/3/library/string.html#formatspec format string syntax] <code>f&quot;Some string {python expression}&quot;</code> defines how to embed values.<br />
<br />
It's generally very straightforward: A formatted string is <code>f&quot;content&quot;</code>, where <code>content</code> can contain <code>{}</code>, which in turn contain an expression (e.g., a variable name like <code>number</code>, or also formatting instructions):<br />
<br />
<syntaxhighlight lang="python">f"The received int32 is {rx_value:b}"</syntaxhighlight><br />
will apply the <code>b</code> format to the variable <code>rx_value</code>. <code>b</code> prints a binary representation of the value. <code>x</code> prints a hexadecimal representation, wheras <code>e</code> can be used on floating point numbers to express them in exponential notation (<code>f&quot;{1/90000:e}&quot;</code> becomes <code>1.111111e-05</code>). For more information on formats, see the [https://docs.python.org/3/library/string.html#formatspec format string syntax].<br />
<br />
=== Setting Log Level ===<br />
<br />
For GNU Radio [https://github.com/gnuradio/gnuradio/blob/v3.10.5.0/gnuradio-runtime/python/gnuradio/gr/qa_python_logging.py v3.10.5+], log level can be changed using <syntaxhighlight lang="python" inline>gr.logging().set_default_level(gr.log_levels.warn)</syntaxhighlight>.<br />
<br />
== Logging in C++ ==<br />
<br />
If you're writing a block, you will already find <code>d_logger</code> as a member of your block. It is a smart pointer to a logger object. This logger is already set up correctly to log messages with a prefix that quotes your block's alias.<br />
<br />
The different log levels are member functions of the logger, so you can log an error using <code>d_logger-&gt;error(…)</code> and a debug message using <code>d_logger-&gt;debug(…)</code>.<br />
<br />
So, in case you need to log a warning, e.g., when a value is invalid and has been replaced, you would follow this example<br />
<br />
<syntaxhighlight lang="c++">void my_block::gain_msg_handler(const pmt::pmt_t& message) {<br />
constexpr float min_gain = 1.0;<br />
d_gain = pmt::to_double(message);<br />
if (d_gain <= 0.0) {<br />
d_logger->warn("Attempted to set non-positive gain {}; clipping to {}.", d_gain, min_gain);<br />
d_gain = min_gain;<br />
}<br />
}</syntaxhighlight><br />
Outside of blocks, you will have to create your own logger. You simply instantiate a <code>gr::logger</code> with the name of the logging &quot;thing&quot; as constructor parameter. An example of that is show below:<br />
<br />
<syntaxhighlight lang="c++">#include <gnuradio/logger.h><br />
<br />
class my_thing<br />
{<br />
private:<br />
gr::logger _logger;<br />
<br />
public:<br />
my_thing(const std::string& name)<br />
: _logger("my thing " + name)<br />
{<br />
_logger.info("constructed");<br />
}<br />
~my_thing() { _logger.warn("I don't like being destructed!"); }<br />
};<br />
<br />
int main() { my_thing thing("gizmo"); }</syntaxhighlight><br />
=== Logging Values ===<br />
<br />
Since <code>gr::logger</code> is a wrapper around <code>spdlog</code>'s logging facilities, it offers the same [https://fmt.dev <code>fmt</code>]-based string formatting.<br />
<br />
An example of that was shown in <code>gain_msg_handler</code> above:<br />
<br />
<syntaxhighlight lang="c++">d_logger->warn("Attempted to set non-positive gain {}; clipping to {}.", d_gain, min_gain);</syntaxhighlight><br />
The <code>{}</code> get replaced (in their respective order) by the arguments to the logging function.<br />
<br />
You can also set the format of fields by using a format specifier syntax very close to Python's ''format string'' syntax. For the actual full syntax definition, refer to [https://fmt.dev/latest/syntax.html <code>fmt</code>'s specification].<br />
<br />
This being C++, the type of the argument specifies already what type of conversion to use (unlike e.g. libc's <code>printf</code>, where you need to tell <code>printf</code> that an integer needs to be interpreted as an integer), so in most cases, you do not need to specify a format. However, sometimes enforcing a specific notation can be helpful for interpretation.<br />
<br />
The format specification follows a colon <code>:</code>. Common examples of things that you might want:<br />
<br />
* '''Formatting floating point in scientific notation''': <code>logger.warn(&quot;Amplitude {:e} out of range&quot;, value);</code> Here, <code>e</code> causes the number passed in to be represented in scientific notation. Use <code>g</code> instead to only apply for large numbers.<br />
* '''Formatting a value with fixed width''': <code>logger.warn(&quot;Count {: +15} out of range&quot;, count);</code> Here, the format specification consists of a space <code> </code>, which is the ''fill character'' to be used to pad to the specified length of <code>15</code> characters, and <code>+</code> denotes that the sign should always be printed (not only for negative numbers). Works with numbers just as well as with strings.<br />
* '''Formatting data in hexadecimal''': <code>logger.info(&quot;Got data {:X}&quot;, data_as_integer_of_any_width)</code>: Print using uppercase hexadecimal (<code>13CAFE37</code>). Use <code>:x</code> for lower case, and use <code>:#x</code> or <code>:#X</code> to get a <code>0x</code> prefix.<br />
* '''Formatting integers as binary''': <code>logger.warn(&quot;Value {:b} is not a valid code word. Corrected to {:b}.&quot;, rx_word, code_word);</code>. Use <code>:#b</code> to get a <code>0b</code> prefix.<br />
<br />
=== Performance Considerations ===<br />
<br />
==== Logger Construction Cost ====<br />
<br />
While constructing a logger is not very expensive, it's still not something you want to do within a hot loop, as it requires inter-thread coordination. Ideally, you want your entity to hold onto a logger object once it's been created. (This is solved through the <code>d_logger</code> member if you're writing a GNU Radio block. Elsewhere, define your own member if in a class context.)<br />
<br />
==== Logging Cost – Disabled Logging ====<br />
<br />
It's possible to disable logging at compile time (it's not recommended, logging is universally quite useful). Or, that the minimum log level was set to higher than a message's log level, so that, for example <code>d_logger-&gt;trace(&quot;val: {: +15g}&quot;);</code> shouldn't actually do anything.<br />
<br />
There ''is'' an integer comparison at run time that will be incurred by having this logging in the code. Notice, however, that modern CPUs tend to predict that to be false if it happens more often, and even if they didn't, such a comparison is quite cheap (and speculative execution would have continued after the logging in the meantime). Benchmarking showed negligible overhead unless used in tight arithmetic loops. If you ''are'' in the ''rare'' case that you want to log from such a compute-intense place, you would want to wrap the logging in some preprocessor <code>#if</code> magic (or figure out a less invasive place to log).<br />
<br />
The format string evaluation ''only'' happens when the logging actually takes place. So, even complex logging formats (aside from the code size) do not affect the runtime. (It might, however, affect life time of some values, so it's not free of side effects.)<br />
<br />
==== Logging Cost – Active Logging ====<br />
<br />
<code>fmt</code> is seriously [https://github.com/fmtlib/fmt#speed-tests fast]. In fact, it beats things like <code>std::stringstream &lt;&lt;</code> by orders of magnitude. Especially when logging things that should not happen often (<code>warn</code>, <code>error</code> or <code>critical</code>), it's probably a good idea to rather log more useful information than less.</div>Kylehttps://wiki.gnuradio.org/index.php?title=Probe_Rate&diff=13645Probe Rate2023-11-29T17:46:26Z<p>Kyle: fix links</p>
<hr />
<div>[[Category:Block Docs]]<br />
__NOTOC__<br />
<span id="gr_vad"></span><br />
Used to measure throughput (how many items/samples are flowing through per second). Note that this block outputs a message, you will need to use a [[Message Debug]] to display the probe results in the console. <br />
<br />
== Parameters ==<br />
; Min Update Time (ms)<br />
: Minimum update time in milliseconds<br />
<br />
; Update Alpha<br />
: Gain for running average filter<br />
<br />
<div data-vad="3.10,later"><br />
; Name<br />
: Specify for identification of the the Probe Rate block. Useful, for example, when printing the output of multiple Probe Rate blocks, e.g., with [[Message Debug]]<br />
</div><br />
<br />
== Example Flowgraph ==<br />
<br />
In this flowgraph, the Probe Rate block is measuring the sample rate of the Audio Source block.<br />
<br />
[[File:USRP_NBFM_xmt.png|800px]]<br />
<br />
== Source Files ==<br />
<br />
; C++ files<br />
: [https://github.com/gnuradio/gnuradio/blob/main/gr-blocks/lib/probe_rate_impl.cc probe_rate_impl.cc]<br />
<br />
; Header files<br />
: [https://github.com/gnuradio/gnuradio/blob/main/gr-blocks/lib/probe_rate_impl.h probe_rate_impl.h]<br />
<br />
; Public header files<br />
: [https://github.com/gnuradio/gnuradio/blob/main/gr-blocks/include/gnuradio/blocks/probe_rate.h probe_rate.h]<br />
<br />
; Block definition<br />
: [https://github.com/gnuradio/gnuradio/blob/main/gr-blocks/grc/blocks_probe_rate.block.yml blocks_probe_rate.block.yml]</div>Kylehttps://wiki.gnuradio.org/index.php?title=User:Kyle&diff=13050User:Kyle2023-04-04T14:47:42Z<p>Kyle: </p>
<hr />
<div>'''Kyle Logue''' works on Software Defined Radio at ''The Aerospace Corporation'' in El Segundo, California.</div>Kylehttps://wiki.gnuradio.org/index.php?title=CCSDS_Encoder_Definition&diff=13049CCSDS Encoder Definition2023-04-04T14:42:14Z<p>Kyle: </p>
<hr />
<div>[[Category:Block Docs]]<br />
CCSDS Encoding class for convolutional encoding with rate 1/2, K=7, and polynomials [109, 79].<br />
<br />
Uses Phil Karn's (KA9Q) implementation of the CCSDS encoder for rate 1/2, K=7, and CC polynomial [109, 79]. These are non-adjustable in this encoder. For an adjustable CC encoder where we can set the rate, constraint length, and polynomial, see [[CC Encoder Definition]].<br />
<br />
<br />
== Parameters ==<br />
(''R''): <span class="plainlinks">[https://wiki.gnuradio.org/index.php/GNURadioCompanion#Variable_Controls ''Run-time adjustable'']</span><br />
<br />
; Parallelism <br />
: It seems that one can create a tensor of one or two dimensions of encoders. More info is needed on this.<br />
<br />
; Dimension 1<br />
: Active when parallelism > 0<br />
<br />
; Dimension 2<br />
: Active when parallelism > 1<br />
<br />
; Frame bits<br />
: When not being used in a tagged stream mode, this encoder will only process frames of the length provided here. If used in a tagged stream block, this setting becomes the maximum allowable frame size that the block may process.<br />
<br />
; Start state<br />
: Initialization state of the shift register.<br />
<br />
; Streaming behaviour<br />
: Specifies how the convolutional encoder will behave and under what conditions.<br />
:; Streaming: This mode expects an uninterrupted flow of samples into the encoder, and the output stream is continually encoded.<br />
:; Terminated: Mode designed for packet-based systems. This mode adds rate*(k-1) bits to the output as a way to help flush the decoder.<br />
:; Tailbiting: Another packet-based method. Instead of adding bits onto the end of the packet, this mode will continue the code between the payloads of packets by pre-initializing the state of the new packet based on the state of the last packet for (k-1) bits.<br />
:; Truncated: A truncated code always resets the registers to the start state between frames.<br />
<br />
== Example Flowgraph ==<br />
<br />
Insert description of flowgraph here, then show a screenshot of the flowgraph and the output if there is an interesting GUI. Currently we have no standard method of uploading the actual flowgraph to the wiki or git repo, unfortunately. The plan is to have an example flowgraph showing how the block might be used, for every block, and the flowgraphs will live in the git repo.<br />
<br />
== Source Files ==<br />
<br />
; C++ files<br />
: [https://github.com/gnuradio/gnuradio/blob/master/gr-fec/lib/ccsds_encoder_impl.cc ccsds_encoder_impl.cc]<br />
<br />
; Header files<br />
: [https://github.com/gnuradio/gnuradio/blob/master/gr-fec/lib/ccsds_encoder_impl.h ccsds_encoder_impl.h]<br />
<br />
; Public header files<br />
: [https://github.com/gnuradio/gnuradio/blob/master/gr-fec/include/gnuradio/fec/ccsds_encoder.h ccsds_encoder.h]<br />
<br />
; Block definition<br />
: [https://github.com/gnuradio/gnuradio/blob/master/gr-fec/grc/variable_ccsds_encoder_def_list.block.yml variable_ccsds_encoder_def_list.block.yml]</div>Kylehttps://wiki.gnuradio.org/index.php?title=QT_GUI_Label&diff=12925QT GUI Label2023-02-02T23:22:21Z<p>Kyle: added example for formatter; confusing implementation</p>
<hr />
<div>[[Category:Block Docs]]<br />
This block creates a variable with a label widget for text. Leave the label blank to use the variable id as the label.<br />
<br />
== Parameters ==<br />
(''R''): <span class="plainlinks">[https://wiki.gnuradio.org/index.php/GNURadioCompanion#Variable_Controls ''Run-time adjustable'']</span><br />
<br />
; Label<br />
: <br />
<br />
; Type (''R'')<br />
: Type of data to handle<br />
<br />
; Defaut Value (''R'')<br />
: <br />
<br />
; Formatter<br />
: Function returning string. Something like <code>lambda x: f'{x:.3f}'</code> can be used to format a number.<br />
<br />
; GUI Hint<br />
: See [[GUI Hint]] for info about how to organize multiple QT GUIs <br />
<br />
== Example Flowgraph ==<br />
<br />
This flowgraph and output show a QT GUI Label with an id:freq and a value of 0.1 Note that the output shows the <code>Label:</code> value 'Frequency' and the <code>Default Value:</code> value '100.0m'. The <code>freq</code> value is used to set the Signal Source Frequency.<br />
<br />
[[File:QT_GUI_demo.png|800px]]<br />
<br />
== Source Files ==<br />
<br />
; Block definition<br />
: [https://github.com/gnuradio/gnuradio/blob/master/gr-qtgui/grc/qtgui_label.block.yml]</div>Kylehttps://wiki.gnuradio.org/index.php?title=Hackfest1905&diff=5074Hackfest19052019-05-30T22:40:11Z<p>Kyle: added details about the ML working group.</p>
<hr />
<div>= Breakthrough Listen Hackfest at the Allen Telescope Array = <br />
[https://openresearch.institute/breakthrough-listen-2019/ Schedule], [https://github.com/SETIatHCRO/grhack/wiki Wiki], [https://github.com/SETIatHCRO/grhack/ Repo]<br />
<br />
== Topics ==<br />
<br />
=== SigMF Specification Design ===<br />
<br />
'''Description:''' We spent the majority of the hackfest working on the design of SigMF, both discussing current issues / gaps and working through new features and the direction of the effort. Major accomplishments include:<br />
<br />
* A plan for using [https://json-ld.org/ JSON-LD] to link data, provide schema crosswalks, and define machine-parseable extension namespaces.<br />
* The design of a top-level metafile that can be used to describe multi-sensor experiments, while still maintaining the independence of each recording.<br />
* The design of a path to describe the capture hardware for a recording and the experimental setup for a multi-sensor data corpus.<br />
* Numerous other bug fixes and "small" but important details of the specification.<br />
<br />
This work is continuing, and we anticipate the next major release of SigMF to include some of these new developments!<br />
<br />
'''Location:''' Work is occurring in the SigMF Github repository, and will continue there: https://github.com/gnuradio/SigMF<br />
<br />
'''People:''' <br />
* Daina Bouquin<br />
* Katie Frey <br />
* Ben Hilburn ([https://github.com/gnuradio/SigMF @bhilburn], [https://www.deepsig.io/ DeepSig Inc.])<br />
* Tom Rondeau<br />
* Karen Rucker<br />
<br />
'''Contact:'''<br />
* [https://github.com/gnuradio/SigMF SigMF Github Repository]<br />
* #sigmf in [https://slack.gnuradio.org/ GNU Radio Slack]<br />
<br />
=== Wideband Signal Processing via ML ===<br />
The [https://github.com/SETIatHCRO/grhack/wiki/ML-Working-Group ML Working Group] page covers the work completed at the event. A processing pipeline was designed and a series of captures were made from the antenna in SigMF format that should allow such a pipeline to be tested. The captured data is available at the IEEE datastore (link pending upload).<br />
<br />
'''People:''' <br />
* [[User:Kyle|Kyle Logue]], ''The Aerospace Corporation''<br />
* Andres Vila Casado, ''The Aerospace Corporation''<br />
* Donna Branchevsky, ''The Aerospace Corporation''<br />
* Nathan Whitehair, ''The Aerospace Corporation''<br />
* Gerry Zhang, ''Breakthrough Listen Team''<br />
<br />
[[Category:Hackfests]]</div>Kylehttps://wiki.gnuradio.org/index.php?title=User:Kyle&diff=5073User:Kyle2019-05-30T22:39:45Z<p>Kyle: cleanup</p>
<hr />
<div>'''Kyle Logue''' is the Software Defined Radio Lead at ''The Aerospace Corporation'' in El Segundo, California.</div>Kylehttps://wiki.gnuradio.org/index.php?title=User:Kyle&diff=5072User:Kyle2019-05-30T22:37:44Z<p>Kyle: created user page</p>
<hr />
<div>Kyle Logue<br />
Software Defined Radio Group<br />
The Aerospace Corporation</div>Kyle