[prev in list] [next in list] [prev in thread] [next in thread] 

List:       gnuradio-discuss
Subject:    Re: [Discuss-gnuradio] Python block help
From:       Marcus_Müller <marcus.mueller () ettus ! com>
Date:       2017-05-29 22:02:07
Message-ID: 457eed0f-6216-870f-6cce-51608385d335 () ettus ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


Hi Zach,


On 29.05.2017 22:57, Zach Morris wrote:
> Hi Marcus,
>
> Sorry about the trouble with Nabble, I see that my code got cut off. I
> will communicate via the mailing list from now on.
>
> If I understand your explanation correctly, the forecast function
> below tells the scheduler that this block needs at least noutput_items
> on each input port in order to produce noutput_items. In actuality, my
> arbitrary ratio block would produce anywhere between (0,
> noutput_items); would this be a valid implementation of forecast() for
> my arbitrary ratio block?
> def forecast(self, noutput_items, ninput_items_required):
>     for i in range(len(ninput_items_required)):
>          ninput_items_required[i] = noutput_items
>
yes, that would tell the scheduler that you'll need at least
noutput_items input items to produce noutput_items output items, indeed!

Now, the forecast really is just that: a forecast. If you can't produce
as many samples as promised, the scheduler won't be upset.
>
> This is my general_work() function right now: it just outputs the
> elements in the input vector that are above a threshold. My eventual
> goal is to receive a vector from an FFT and update statistics for each
> frequency 'bin' as long as its power is above a threshold, then output
> the statistics when its power drops below the threshold.

> def general_work(self, input_items, output_items):
>      in0 = input_items[0][:len(output_items[0])]
This is **only** OK if you check that len(output_items[0]) <=
len(input_items[0]). You inherently do that with your forecast, but I'd
really recommend explicitly checking that condition.
Also, this the following code is really very redundant:
>      out0 = output_items[0]
>      ninput_items = len(in0)
well, you set in0 to be of len(output_items[0]).
>
>      j = 0
>      for i in range(0, ninput_items):
this is very un-pythonic.
>          if (in0[i] > self.threshold).all(): 
>              out0[j] = in0[i]
>               j += 1
>
I'd just say:

def general_work(self, input_items, output_items):
    super_threshold = filter(lambda x: x > self.threshold, in[0])
    output_items[0][:] = super_threshold
    self.consume_each(len(super_threshold))
    return len(super_threshold)

Best regards,
Marcus

>      self.consume(0, ninput_items)
>      self.produce(0, j)
>
>      return 0
>
> If I again understand your explanation, the 'self.consume(0,
> ninput_items)' is correct, because I 'use up' the elements of
> input_items on each loop. However, it sounds like I should either
> return WORK_CALLED_PRODUCE or return ninput_tems. Am I on the right
> track here? Is there a reason to prefer produce() over just returning
> the number of input items I consume?
>
> Thank you for your help.
>
> Zach
>
>
> On Sun, May 28, 2017 at 1:31 PM, Marcus Müller
> <marcus.mueller@ettus.com <mailto:marcus.mueller@ettus.com>> wrote:
>
>     Hi Zach,
>
>     sorry it took me so long to react:
>     so, let's dissect a few things:
>
>     First, the general purposes of these functions:
>
>     * forecast() is called by the *scheduler* to ask your block "hey,
>     if I'd
>     need you to produce N items, how much would you need on your 0.
>     (and 1.,
>     and 2.,… if existing) input for that?". The scheduler usually
>     repeatedly
>     calls that with a decreasing N until the number of samples your block
>     requires can be fulfilled by the number of input items that the
>     scheduler has ready. If that never happens, usually, something is
>     broken.
>
>     * consume() is something that *you* call from within a
>     (general_)work()
>     to signal the scheduler how many items you've consumed from the
>     input(s).
>
>     * produce() is something that *you* call from within a
>     (general_)work()
>     to signal the scheduler how many items you've put into the output
>     buffer. *If* you use produce, you should return the magic
>     WORK_CALLED_PRODUCE values. You usually don't call produce() – you
>     just
>     return the number of consumed samples instead.
>
>     * noutput_items is **not** a variable that you set – it's the info how
>     many items you are asked to produce (parameter to forecast()) or how
>     many items you're **allowed at most** to produce (when it's the
>     parameter to a (general_)work())
>
>     Again, the better parts of your mail have been broken by Nabble.
>     Abandon
>     Nabble. Subscribe directly:
>
>     https://lists.gnu.org/mailman/listinfo/discuss-gnuradio
>     <https://lists.gnu.org/mailman/listinfo/discuss-gnuradio>
>
>     Hope that helps,
>     Marcus
>
>     On 05/26/2017 07:49 PM, Zach Morris wrote:
>     > That worked to create a general block, but I'm still having some trouble with
>     > implementing the forecast(), consume() and produce() functions.
>     >
>     > The goal of the block is to discard elements in an input vector
>     that are
>     > below a certain threshold, and eventually update some statistics
>     based on
>     > the remaining elements. For a vector of 256 elements, there could be
>     > anywhere between 0 and 256 outputs (the arbitrary ratio you
>     mentioned).
>     >
>     > The default forecast function has a 1:1 ratio:
>     >
>     > Should I replace "noutput_items" with my "vector_length" parameter, ensuring
>     > that we always get (for example) 256 inputs?
>     >
>     > In the general_work function, I think we want to consume the
>     entire input
>     > vector once we figure out which elements are above the threshold:
>     >
>     > I'm not sure about the produce function; do I need to tell the system how
>     > many items I produce, or is that covered at the end of general_work:
>     >
>     >
>     > Thank you kindly,
>     >
>     > Zach
>     >
>     >
>     >
>     >
>     > --
>     > View this message in context:
>     http://gnuradio.4.n7.nabble.com/Python-block-help-tp51706p64062.html
>     <http://gnuradio.4.n7.nabble.com/Python-block-help-tp51706p64062.html>
>     > Sent from the GnuRadio mailing list archive at Nabble.com.
>     >
>     > _______________________________________________
>     > Discuss-gnuradio mailing list
>     > Discuss-gnuradio@gnu.org <mailto:Discuss-gnuradio@gnu.org>
>     > https://lists.gnu.org/mailman/listinfo/discuss-gnuradio
>     <https://lists.gnu.org/mailman/listinfo/discuss-gnuradio>
>
>
>     _______________________________________________
>     Discuss-gnuradio mailing list
>     Discuss-gnuradio@gnu.org <mailto:Discuss-gnuradio@gnu.org>
>     https://lists.gnu.org/mailman/listinfo/discuss-gnuradio
>     <https://lists.gnu.org/mailman/listinfo/discuss-gnuradio>
>
>


[Attachment #5 (text/html)]

<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <p>Hi Zach,<br>
    </p>
    <br>
    <div class="moz-cite-prefix">On 29.05.2017 22:57, Zach Morris wrote:<br>
    </div>
    <blockquote
cite="mid:CA+M1yVdvrYAoyFB4v-WxTWkKjOm_0iFkP4+3R_FME-yG9Dp2mg@mail.gmail.com"
      type="cite">
      <div dir="ltr">Hi Marcus,
        <div><br>
        </div>
        <div>Sorry about the trouble with Nabble, I see that my code got
          cut off. I will communicate via the mailing list from now on.</div>
        <div><br>
        </div>
        <div>If I understand your explanation correctly, the forecast
          function below tells the scheduler that this block needs at
          least noutput_items on each input port in order to produce
          noutput_items. In actuality, my arbitrary ratio block would
          produce anywhere between (0, noutput_items); would this be a
          valid implementation of forecast() for my arbitrary ratio
          block?<br>
        </div>
        <div>
          <div>def forecast(self, noutput_items, ninput_items_required):<br>
          </div>
          <div>    for i in range(len(ninput_items_<wbr>required)):</div>
          <div>         ninput_items_required[i] = noutput_items</div>
          <div><br>
          </div>
        </div>
      </div>
    </blockquote>
    yes, that would tell the scheduler that you'll need at least
    noutput_items input items to produce noutput_items output items,
    indeed!<br>
    <br>
    Now, the forecast really is just that: a forecast. If you can't
    produce as many samples as promised, the scheduler won't be upset.<br>
    <blockquote
cite="mid:CA+M1yVdvrYAoyFB4v-WxTWkKjOm_0iFkP4+3R_FME-yG9Dp2mg@mail.gmail.com"
      type="cite">
      <div dir="ltr">
        <div>
          <div><br>
          </div>
          <div>This is my general_work() function right now: it just
            outputs the elements in the input vector that are above a
            threshold. My eventual goal is to receive a vector from an
            FFT and update statistics for each frequency 'bin' as long
            as its power is above a threshold, then output the
            statistics when its power drops below the threshold. <br>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
    <blockquote
cite="mid:CA+M1yVdvrYAoyFB4v-WxTWkKjOm_0iFkP4+3R_FME-yG9Dp2mg@mail.gmail.com"
      type="cite">
      <div dir="ltr">
        <div>
          <div>def general_work(self, input_items, output_items):<br>
          </div>
          <div>     in0 = input_items[0][:len(output_<wbr>items[0])]</div>
        </div>
      </div>
    </blockquote>
    This is **only** OK if you check that len(output_items[0]) &lt;=
    len(input_items[0]). You inherently do that with your forecast, but
    I'd really recommend explicitly checking that condition. <br>
    Also, this the following code is really very redundant:<br>
    <blockquote
cite="mid:CA+M1yVdvrYAoyFB4v-WxTWkKjOm_0iFkP4+3R_FME-yG9Dp2mg@mail.gmail.com"
      type="cite">
      <div dir="ltr">
        <div>
          <div>     out0 = output_items[0]</div>
          <div>     ninput_items = len(in0)</div>
        </div>
      </div>
    </blockquote>
    well, you set in0 to be of len(output_items[0]).<br>
    <blockquote
cite="mid:CA+M1yVdvrYAoyFB4v-WxTWkKjOm_0iFkP4+3R_FME-yG9Dp2mg@mail.gmail.com"
      type="cite">
      <div dir="ltr">
        <div>
          <div><br>
          </div>
          <div>     j = 0</div>
          <div>     for i in range(0, ninput_items):</div>
        </div>
      </div>
    </blockquote>
    this is very un-pythonic.<br>
    <blockquote
cite="mid:CA+M1yVdvrYAoyFB4v-WxTWkKjOm_0iFkP4+3R_FME-yG9Dp2mg@mail.gmail.com"
      type="cite">
      <div dir="ltr">
        <div>
          <div>         if (in0[i] &gt; self.threshold).all(): </div>
          <div>             out0[j] = in0[i]</div>
          <div>              j += 1</div>
          <div><br>
          </div>
        </div>
      </div>
    </blockquote>
    I'd just say: <br>
    <br>
    def general_work(self, input_items, output_items):<br>
        super_threshold = filter(lambda x: x &gt; self.threshold, in[0])<br>
        output_items[0][:] = super_threshold<br>
        self.consume_each(len(super_threshold))<br>
        return len(super_threshold)<br>
    <br>
    Best regards,<br>
    Marcus<br>
    <br>
    <blockquote
cite="mid:CA+M1yVdvrYAoyFB4v-WxTWkKjOm_0iFkP4+3R_FME-yG9Dp2mg@mail.gmail.com"
      type="cite">
      <div dir="ltr">
        <div>
          <div>     self.consume(0, ninput_items)<br>
          </div>
          <div>     self.produce(0, j)</div>
          <div><br>
          </div>
          <div>     return 0</div>
        </div>
        <div><br>
        </div>
        <div>If I again understand your explanation, the
          'self.consume(0, ninput_items)' is correct, because I 'use up'
          the elements of input_items on each loop. However, it sounds
          like I should either return WORK_CALLED_PRODUCE or return
          ninput_tems. Am I on the right track here? Is there a reason
          to prefer produce() over just returning the number of input
          items I consume?</div>
        <div><br>
        </div>
        <div>Thank you for your help.</div>
        <div><br>
        </div>
        <div>Zach</div>
        <div><br>
        </div>
        <div class="gmail_extra"><br>
          <div class="gmail_quote">On Sun, May 28, 2017 at 1:31 PM,
            Marcus Müller <span dir="ltr">&lt;<a moz-do-not-send="true"
                href="mailto:marcus.mueller@ettus.com" \
target="_blank">marcus.mueller@ettus.com</a>&gt;</span>  wrote:<br>
            <blockquote class="gmail_quote" style="margin:0px 0px 0px
              0.8ex;border-left:1px solid
              rgb(204,204,204);padding-left:1ex"><span>Hi Zach,<br>
                <br>
                sorry it took me so long to react:<br>
                so, let's dissect a few things:<br>
                <br>
                First, the general purposes of these functions:<br>
                <br>
                * forecast() is called by the *scheduler* to ask your
                block "hey, if I'd<br>
                need you to produce N items, how much would you need on
                your 0. (and 1.,<br>
                and 2.,… if existing) input for that?". The scheduler
                usually repeatedly<br>
                calls that with a decreasing N until the number of
                samples your block<br>
                requires can be fulfilled by the number of input items
                that the<br>
                scheduler has ready. If that never happens, usually,
                something is broken.<br>
                <br>
                * consume() is something that *you* call from within a
                (general_)work()<br>
                to signal the scheduler how many items you've consumed
                from the input(s).<br>
                <br>
                * produce() is something that *you* call from within a
                (general_)work()<br>
                to signal the scheduler how many items you've put into
                the output<br>
                buffer. *If* you use produce, you should return the
                magic<br>
                WORK_CALLED_PRODUCE values. You usually don't call
                produce() – you just<br>
                return the number of consumed samples instead.<br>
                <br>
                * noutput_items is **not** a variable that you set –
                it's the info how<br>
              </span>many items you are asked to produce (parameter to
              forecast()) or how<br>
              <span>many items you're **allowed at most** to produce
                (when it's the<br>
                parameter to a (general_)work())<br>
                <br>
                Again, the better parts of your mail have been broken by
                Nabble. Abandon<br>
                Nabble. Subscribe directly:<br>
                <br>
                <a moz-do-not-send="true"
                  href="https://lists.gnu.org/mailman/listinfo/discuss-gnuradio"
                  rel="noreferrer" \
target="_blank">https://lists.gnu.org/mailman/<wbr>listinfo/discuss-gnuradio</a><br>  \
<br>  Hope that helps,<br>
                Marcus<br>
                <br>
                On 05/26/2017 07:49 PM, Zach Morris wrote:<br>
              </span><span>&gt; That worked to create a general block,
                but I'm still having some trouble with<br>
                &gt; implementing the forecast(), consume() and
                produce() functions.<br>
                &gt;<br>
                &gt; The goal of the block is to discard elements in an
                input vector that are<br>
                &gt; below a certain threshold, and eventually update
                some statistics based on<br>
                &gt; the remaining elements. For a vector of 256
                elements, there could be<br>
                &gt; anywhere between 0 and 256 outputs (the arbitrary
                ratio you mentioned).<br>
                &gt;<br>
                &gt; The default forecast function has a 1:1 ratio:<br>
                &gt;<br>
              </span><span>&gt; Should I replace "noutput_items" with my
                "vector_length" parameter, ensuring<br>
                &gt; that we always get (for example) 256 inputs?<br>
                &gt;<br>
                &gt; In the general_work function, I think we want to
                consume the entire input<br>
                &gt; vector once we figure out which elements are above
                the threshold:<br>
                &gt;<br>
              </span><span>&gt; I'm not sure about the produce function;
                do I need to tell the system how<br>
                &gt; many items I produce, or is that covered at the end
                of general_work:<br>
                &gt;<br>
                &gt;<br>
              </span>&gt; Thank you kindly,<br>
              &gt;<br>
              &gt; Zach<br>
              &gt;<br>
              &gt;<br>
              &gt;<br>
              <span class="gmail-m_-9051442579776840935HOEnZb"><font
                  color="#888888">&gt;<br>
                  &gt; --<br>
                  &gt; View this message in context: <a
                    moz-do-not-send="true"
href="http://gnuradio.4.n7.nabble.com/Python-block-help-tp51706p64062.html"
                    rel="noreferrer" \
target="_blank">http://gnuradio.4.n7.nabble.co<wbr>m/Python-block-help-tp51706p64<wbr>062.html</a><br>
  </font></span>
              <div class="gmail-m_-9051442579776840935HOEnZb">
                <div class="gmail-m_-9051442579776840935h5">&gt; Sent
                  from the GnuRadio mailing list archive at Nabble.com.<br>
                  &gt;<br>
                  &gt; ______________________________<wbr>_________________<br>
                  &gt; Discuss-gnuradio mailing list<br>
                  &gt; <a moz-do-not-send="true"
                    href="mailto:Discuss-gnuradio@gnu.org"
                    target="_blank">Discuss-gnuradio@gnu.org</a><br>
                  &gt; <a moz-do-not-send="true"
                    href="https://lists.gnu.org/mailman/listinfo/discuss-gnuradio"
                    rel="noreferrer" \
target="_blank">https://lists.gnu.org/mailman/<wbr>listinfo/discuss-gnuradio</a><br>  \
<br>  <br>
                  ______________________________<wbr>_________________<br>
                  Discuss-gnuradio mailing list<br>
                  <a moz-do-not-send="true"
                    href="mailto:Discuss-gnuradio@gnu.org"
                    target="_blank">Discuss-gnuradio@gnu.org</a><br>
                  <a moz-do-not-send="true"
                    href="https://lists.gnu.org/mailman/listinfo/discuss-gnuradio"
                    rel="noreferrer" \
target="_blank">https://lists.gnu.org/mailman/<wbr>listinfo/discuss-gnuradio</a><br>  \
</div>  </div>
            </blockquote>
          </div>
          <br>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>



_______________________________________________
Discuss-gnuradio mailing list
Discuss-gnuradio@gnu.org
https://lists.gnu.org/mailman/listinfo/discuss-gnuradio


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic