This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm whether you accept or reject these cookies being set.

A cookie will be stored in your browser regardless of choice to prevent you being asked this question again. You will be able to change your cookie settings at any time using the link in the footer.

How to shift buffers?
#1
Hello there,
I want to ask about some best practices for shifting buffer content.
My current implementation of such a buffer shift is a combination of append and subrange modules, is a little lengthy, and consumes probably too much power during the experiment.
The append module seems to add buffer values each time it is being executed, which would be more often than the (location) sensor delivers new data (approx. at 1 Hz); interestingly the append module seems to be slower that the linear acceleration sensor (approx. 208.9 Hz on my device).
To avoid an ever growing buffer (due to appending all the time) a subrange module needs to cut off the buffer in the frequency of new sensor data.

Buffer shift could be used for several things:
  • general usage is to construct buffers based on different sensors and based on own calculations in a way that they fit to each other for being displayed during the experiment and at the same time when exporting them (same buffer length which corresponding data at the same position for later reuse in OpenOffice or QGIS, for example), actually the export is the most important reason for juggling with the data this way
  • based on 3 GPS points (6 horizontal coordinates) my experiment calculates UTM coordinates and then the curvature radius for these 3 points and the lateral acceleration, for the overall calculation I use the append/subrange buffer build technique 15 times, yep, the mobile phone is getting warm during the experiment
  • to clock data from one sensor with the new data frequency of another sensor (currently I try to synchronize linear acceleration data with location data, which in principle works, but I don't see yet in an easy way some correlation between my additionally calculated data and the measured acceleration data, some puzzle piece still missing)
  • minor usage example: on my Android devices the location sensor sensor seems to start right away with a location even when before the firt GPS fix, I cut off this 0th location (this situation has been discussed within this thread)

In the attached example the lat buffer (size 0) is being counted and the third most recent position (size 1) is taken (subtract/subrange modules).
Then there is the append/subrange combination which feeds in their output as input for each other.
From what I understand currently this crossed reverse input would correspond to a sub-cycle resolution in the implementation which does not seem to be supported by the visual editor. This only works when I put these two module manually in the XML file in the correct order (subrange ahead of append). Yep, it might be that this technique will not work on each mobile device, but on mine it does.
The if condition is just to only output data if at least 3 GPS fixes are there and I have a set of 3 points to work on.
The subrange module then is to cut off the first buffer element which is an artifact by the append/subrange combination before.

If I'm not wrong some shift buffer module could do the job more easily. Such a module could have two inputs, the original buffer and the number of positions the original buffer should be shifted (+/-). It just might be like the append buffer with settings in which the position shift could be configured.
Or it might be just some shifting in the function module, where the (1st) input buffer is being refeneces as [1_], isn't it?
Some shifting could be configured as [1_(-1)] when using buffer [1] in the formular.
I outlined this just for giving these example and a better understanding of my intention.

Since I'm a new user of phyphox there is a lot I do not know, of course.
Maybe you already have something I could use for shifting buffers. Any idea welcome.
Thanks and kind regards, Trikes.


Attached Files Thumbnail(s)
   
Reply
#2
Sorry, I am a bit in a hurry right now and did not have a chance to thorowly look into your example, but I have a few pointers that I would like to drop quickly. I hope they are not beside the topic:
  • The current editor is outdated compared to the current file format of phyphox. Its output works, but it does not offer all features that are available now. We are about to release a new editor, but we are a bit stuck in a testing-fix-testing-loop. As soon as there are not too many bugs found by our weekly test with students the new version will be made available as a public beta. Until then, you should probably resort to editing the XML file directly if you want to optimize in such details.
  • You are right that most operations like subrange are quite expensive if you have a large dataset. The way our flexible file format is implemented requires a full copy of the range that is copied by the subrange module as well as the append module or any other module as phyphox does not look ahead to check if the inputs are still used later (this is not apparent from how the old editor displays the logic). This will always be true for operations that increase the buffer size, but I could look into at least optimizing subrange in case that the clear falg is set on the input.
  • Be careful about buffers that are directly connected to graphs. Doing anything to them that is more complicated than just appending new values is rather expensive as they retain a copy of their data that has been prepared for OpenGL and they will have to rebuild that data if anything more complicated happens.
  • The most efficient way to shift values - at least if what you need is a fixed number of values - is setting a fixed buffer size, which will have a shifting effect. If you need control over new data, you could write the sensor data into a separate buffer, process new data and also copy it into a buffer with fixed size. This should be more efficient as only the new data is copied while the larger set of old data is handled by the fixed-size buffer.
  • There are a few new features that the old editor did not yet support, which might be interesting for your case: The split module helps if you want to process new incoming data, but need to keep some of it around for the next cycle. The requireFill attribute of the analysis block (and related attributes) helps to only run the analysis process if you have new data.
  • And on the subject of synchronizing sensors: Did you see the rateStrategy attribute (another one that is not in the old editor)? This allows to force a specific rate of the sensor - unfortunately each strategy has its downside as we cannot force the device's sensor to actually run at a specific rate.

Now, that reply became longer than expected, so I hope there is something helpful in there Smile
Reply
#3
Thanks a lot for all the suggestions. I believe that the split module should be able to reduce some containers in my experiment, because the split could, of course, as well happens at the start of  a buffer. In the exported data file I would expect for the split buffers some NaN entries at the most recent positions when compared to the one un-split buffer which I still need for the building up the data (details skipped). I tried to enter the split module in the XML file but failed somehow, I would wait for some example given in the documentation you linked.

The visual editor has some input validation? When adding a not yet supported module manually to the XML file the visual editor won't accept that XML anymore, because it could not save later on that unsupported module? Ah, the visual editor accepts reading yet unsupported attributes, but does not write them back. Then I will continue with the visual editor to finish the experiment and only later on would try the manual optimization in the XML file.

The requireFill attribute should save some if modules in my experiment. This attribute I can use multiple times, I would expect. But the other two, requireFillThreshold and requireFillDynamic, I can only define one time, because they do not related to a specific buffer? No, also requireFill I can define only one time, isn't? It is an attribute to the analysis module and not to the data container (buffer).

Next thing I want to try is to relate in a meaningful way the accelerations from the linear acceleration sensor with the calculated lateral accelaration in a curve to verify the g's against each other. Don't see yet any strong correlation between the numbers.

Cheers Smile
Reply
#4
Seems like you answered most of the questions yourself Smile

The visual editor does some half-hearted validation. But it can only use modules that are known to it and it will generate the entire XML file from scratch, so there is no way to use it with new modules.

requireFill is only designed to observe a single buffer and it is indeed an attribute to the analysis tag. Since it controls if the analysis modules are executed at all, there is no workaround to observe multiple buffers at the moment.

Here is an example of how I use the split module to calculate a moving average of 100 values. The split module keeps enough values (99) around for the next iteration, so the moving average has enough historic values to continue with the next new value. Note, that this is somewhat specific to the moving average module as it has the option to only output results when it has consumed enough values. Also note, that if you would try this example, the results on Android would be wrong as I made a mistake when implementing the movingaverage. It will be fixed in the next release.

Code:
<phyphox version="1.18" locale="en">
    <title>Moving average demo</title>
    <category>Test</category>
    <description>Demo for the new movingaverage and split analysis modules.</description>
    <data-containers>
        <container size="0">accT</container>
        <container size="0">accNew</container>
        <container size="0">accTodo</container>
        <container size="0">accRaw</container>
        <container size="0">accAvg</container>
    </data-containers>
    <input>
        <sensor type="accelerometer">
            <output component="t">accT</output>
            <output component="z">accNew</output>
        </sensor>
    </input>
    <views>
        <view label="Graph">
            <graph label="z Raw" timeOnX="true" labelX="[[quantity_short_time]]" unitX="[[unit_short_second]]" labelY="[[quantity_short_acceleration]]" unitY="[[unit_short_meter_per_square_second]]" unitYperX="m/s³" partialUpdate="true" color="red">
                <input axis="x">accT</input>
                <input axis="y">accRaw</input>
            </graph>
            <graph label="z Moving Average" timeOnX="true" labelX="[[quantity_short_time]]" unitX="[[unit_short_second]]" labelY="[[quantity_short_acceleration]]" unitY="[[unit_short_meter_per_square_second]]" unitYperX="m/s³" partialUpdate="true" color="green">
                <input axis="x">accT</input>
                <input axis="y">accAvg</input>
            </graph>
        </view>
    </views>
    <analysis requireFill="accNew" requireFillThreshold="100">

        <split>
            <input as="data">accNew</input>
            <input as="overlap" type="value">99</input>
            <output>accTodo</output>
            <output>accNew</output>
        </split>

        <subrange>
            <input keep="true">accTodo</input>
            <input as="from" type="value">99</input>
            <output append="true">accRaw</output>
        </subrange>

        <movingaverage dropIncomplete="true">
            <input as="data">accTodo</input>
            <input as="width" type="value">100</input>
            <output append="true">accAvg</output>
        </movingaverage>

    </analysis>
</phyphox>

If I ever come across a time machine I will rewrite phyphox with Python support instead of its own exotic XML-based language Smile
Reply
#5
For now only a quick update on the order of modules in the XML file as exported by the editor:
  • it is not necessary to edit the order manually in the XML file as I did before to ensure the correct buffer build up (my last screenshot above)
  • it appears that the editor defines the order of the modules at export by their horizontal position "posx" like in
    Quote:<subrange editor:uuid="2460" editor:posx="350" editor:posy="920">
  • in the past weeks, I think, I read in some resource something about the horizontal order but have not found this source again (I believe, it was something like horizontal order is used and vertical order is not; remembered this only again vaguely yesterday)
  • at my attempt before I manually adjusted the "posx" and "posy" values in XML to have a nice looking view on the experiment in the editor (in the next editor version there could be some "snap to grid" function to avoid that the positions have decimal numbers in which the significant difference which decides on the execution order happens at the 8th position after the decimal point, which is kind of hard to see in an XML file of a thousand lines), this way (XML edit) the two important modules (buffer element source and loss terms, last screenshot) had the same "posx" and their vertical order had most probably being ignored at export, allowing me to define it manually in XML (just in terms of line numbers, simply by copying a module ahead of the other in the file), this reordering in XML was then in contradiction to the "posy" values of the modules as from the editor, but this was without any impact
  • to avoid the manual XML edit I use now some small posx offset (10) to ensure that one of the modules is being executed ahead of the other to have a correct buffer build (new screenshot)
  • well, at least this is my current undestanding after some experimental changes in the XML file and importing/experting it to/from the editor several times, still need to test my experiment after introducing this small offset for all such buffer builds



Attached Files Thumbnail(s)
   
Reply
#6
You are right: the (old) editor is reading from left to right. The new editor is blockly based, so there is a strict vertical order – and almost no flexibility to spend time on arranging elements on the screen… Wink
Reply
#7
Yeah, that is another reason why we are abandoning the old editor. They way it presents the experiment suggests an order based on connections. You would expect that if you connect module A to module B, A would be executed first (like in LabView if youa re familiar with that). But phyphox does not have such hirachy and infact there are some cases in which you might get a result from the last module that is executed and want to use that result in the next iteration.

So, to be clear: The posx and posy (like anything with an "editor:"-prefix in the XML file) is entirely ignored by phyphox. If you change these, it will affect how the configuration is loaded in the editor, but not how it is interpreted by phyphox. It only has an effect in phyphox if you load it into the editor and then export it again, because the editor will generate the order of the module in the analysis-block based on the x-position. (A desperate attempt to be able to represent experiments with different module order in the editor while remaining intuitiv for users with simple configurations.)
Reply
#8
Well, don't bash the old editor too hard. It offers a low entry level for a seldom programming experience. What I mean:

When you discover Phyphox some first thought is, wow, I can do something with the sensors, cool.
When you start developing your own experiment some dark thoughts arise, how could this be working at all?
What is the base frequency in which the experiment is being executed?
The location sensor is at about 1 Hz, the linear acceleration is at something above 200 Hz, and an independent append module is at something in-between.
A linear programming paradigm does not apply.
How could I develop anything at all in Phyphox?
I started developing my (first) experiment about 4 weeks ago.
And only 3 weeks ago I got some understanding of how I could do things, when I was thinking about analogue computers and how to program them.
With the visual editor you do not implement directly your algorithm as you do in the more common linear programming languages.
Instead you define bondary conditions for the data flow routes (modules, buffers, connections; notice that buffers themselves are also kind of a module with which you can encode some behavior). Just as you would design for an analogue computer the size of containers, the diameter of tubes, the resistence of a wire, etc. And instead of water or electrical current, sensor data is running through the experiment, with each data source having its own frequency. I think, it is more like some multi-frequency, parallel spreadsheet calculation than like a shell script.

For me it is a seldom opportunity to have this kind of programming experience.
And maybe this kind of programming experience is even more important in terms of didactics than "just" reading out some sensor data.
Sure, the sensor data is important if you want to use Phyphox for your physical experiments.
Maybe this unique programming experience is an equally important feature of your app and deserves some own article; which might already exist, I cannot tell. In the end, Phyphox is providing its own programming language for an event-driven real time environment, isn't it? Maybe this is not seen in the public as Phyphox' major feature. (Not sure about your Python statement. Better to not provide the opportunity of code injection to a mobile phone. Currently you have with your own programming language an encapsulated system in which only your rules apply, I would not allow experiments defined as Python or any other code.)

Only when I had that non-linear understanding of what I do in the editor, I was able to shortcut the modules (that evil "X" in the module connectins in my screenshots before) and could rip apart buffers and build them up again with each cycle, at whatever frequency the cycles would have, the frequency is no longer important. Hmm, sometimes I understand how this "X" works, but then there are also times when I'm no longer that sure how it could work at all. For sure it is not trivially working, and for sure it is only working when several of these modules are being executed in the correct order, not only the two modules connected with the "X", but others as well. Would be interested in your detailed explanation how this would really work.

I would have the hope that the new editor does not introduce limitations compared to the old editor, meaning that I could use the new editor to continue to edit experiments that I started to develop in the old one (that evil "X"). Sure, would be also nice if the new editor would offer some help for this "non-linear" programming style. Maybe also that the new editor could be completely independant from any module specific definition, in a way that it does not get outdated when you invent new modules. You could consider to have the module definitions independently from the editor implemention as some schema that you could separately provide and update any time when you come up with a new module or enhance an existing one.

My hope would be that the new editor could do the thing from my attachment without the need to change anything in the implementation of this experiment.
If you deprecate the old editor it would be still around and could be used in some legacy mode? Which more or less is already the current status quo, isn't?

Well, it is only my personal opinion and I do not claim to have understood it completely. Cheers Smile


Attached Files Thumbnail(s)
   
Reply
#9
(Top secret: a link to the new editor is already in this forum. Expect –hopefully less'n'less– breakages. Wink)
Reply
#10
(I won't tell anybody. Thanks.)

(I loaded my experiment into the new editor, changed only its name, nothing else, and loaded it via QR into the same mobil phone. Experiment does not work.)

First difference in the XML created by the new editor is that there are no buffer size "1" attributes.

Old editor:
Quote:<container size="1" static="false">lat_count</container>

New editor:
Quote:<container>lat_count</container>

I use other buffer sizes as well, "0", "3", "10", and "1000", they all are available in the new editor's XML, but all buffer size "1" attributes are missing in the XML, but are displayed as "1" in the Web UI of the new editor.

New editor:
Quote:<container size="3">UTM_Easting</container>

People will miss the map and the lines which provide some higher view on more complex algorithms.
The new editor provides a more linear programming experience. I can see the advantages of both editors.
For the moment I stay with the old one.

(Is there already some secret documentation for the new editor?)
Reply


Forum Jump: