How to parse factor/dataframe with Rembedded - c

I am in the process of writing an api that will convert the native SEXP objects to protocol buffers so that I can serialize them. My problem arises when trying to convert a SEXP object from a dataframe using recursive function. The issue is when I find an INTSXP that inherits factor; the factor only sees two levels in the level count. Is there an example somewhere about how to handle a factor in c? Or does someone have advice atleast on why I am only seeing two levels. Also I have a feeling I am going to run into another issue when handling the NA but haven't tried handling that yet.
I am guessing the issue is some internal feature of R is seeing red twice and just creating a pointer when creating the dataframe.
R Version
R version 3.0.2 (2013-09-25)
CODE
Here is the R code that I am executing. It is running through a jni interface and getting back a protocol buffer.
String command = "d <- c(1,2,3,4); e <- c(\"red\", \"white\", \"red\", NA); f <- c(TRUE,TRUE,TRUE,FALSE); mydata <- data.frame(d,e,f);";
Here is where I am handling the types.
case INTSXP: // #define INTSXP 13 /* integer vectors */
// factors have internal type INTSXP too
if (Rf_inherits(model, "factor")) {
int levelCount = Rf_nlevels(model);
if (levelCount > 0) {
fprintf(stderr, "Got a factor with count %d\n", levelCount);
SEXP levels = Rf_getAttrib(model, Rf_install("levels"));
fill_rexp(rexp, levels);
}
break;
}
rexp->rclass = REXP__RCLASS__INTSXP;
rexp->n_intvalue = LENGTH(model);
rexp->intvalue = malloc(sizeof(rexp->intvalue) * (rexp->n_intvalue));
for (i = 0; i < rexp->n_intvalue; i++) {
fprintf(stderr, "Setting value of rexp to %d %d\n",i, (INTEGER(model)[i]));
rexp->intvalue[0] = (INTEGER(model)[i]);
}
break;
case REALSXP: //#define REALSXP 14 /* real variables */
rexp->rclass = REXP__RCLASS__REALSXP;
Notice in the output that the "Got a factor with count 2" is that I thought would be 4. Is there a cleaner way to handle this in c?
Type of model is 19
Size of vector is 3
Type of model is 14
Setting value of rexp to 0 1.000000
Setting value of rexp to 1 2.000000
Setting value of rexp to 2 3.000000
Setting value of rexp to 3 4.000000
Type of model is 13
Got a factor with count 2
Type of model is 16
Number of strings 2
Type of model is 10
Count of children in vector 3

If you're converting a factor to character, you want Rf_asCharacterFactor.

I found a solution that works!! I found the example in the Rcpp. I tried the Rf_coerce to see if that was working in R-3.0.2 but when I tried to coerce it to STRSXP it returned me integers. So I used the example code below to get this to return me the values from the factor.
case INTSXP:
{
// return Rf_coerceVector( x, STRSXP );
// coerceVector does not work for some reason
SEXP call = PROTECT( Rf_lang2( Rf_install( "as.character" ), x ) ) ;
SEXP res = PROTECT( Rf_eval( call, R_GlobalEnv ) ) ;
UNPROTECT(2);
BTW in the future I would have just spent some time learning cpp better and used Rcpp but my experience with cpp is lacking.

Related

may you explain this algorithm of calculate to average for noise

I am working on embedded programming with written code by other people.
this algorithm be used in calculate average for mic and accelerometer
sound_value_Avg = 0;
sound_value = 0;
memset((char *)soundRaw, 0x00, SOUND_COUNT*2);
for(int i2=0; i2 < SOUND_COUNT; i2++)
{
soundRaw[i2] = analogRead(PIN_ANALOG_IN);
if (i2 == 0)
{
sound_value_Avg = soundRaw[i2];
}
else
{
sound_value_Avg = (sound_value_Avg + soundRaw[i2]) / 2;
}
}
sound_value = sound_value_Avg;
acceleromter is similar to this
n1=p1
(n2+p1)/2 = p2
(n3+p2)/2 = p3
(n4+p3)/2 = p4
...
avg(n1~nx)=px
it not seems to be correct.
can someone explain why he used this algorithm?
is it specific way for sin graph? like noise, vibration?
It appears to be a flawed attempt at maintaining a cumulative mean. The error is in believing that:
An+1 = (An + sn) / 2
when in fact it should be:
An+1 = ((An * n) + s) / (n + 1)
However it is computationally simpler to maintain a running sum and generate an average in the usual manner:
S = S + s
An = S / n
It is possible that the intent was to avoid overflow when the sum grows large, but the attempt is mathematically flawed.
To see how wrong this statement is consider:
True
n s Running Avg. (An + sn) / 2
--------------------------------------
1 20 20 20
2 21 20.5 20.25
3 22 21 20.625
In this case however, nothing is done with the intermediate mean value, so you don'e in fact need to maintain a running mean at all. You simply need to accumulate a running sum and calculate the average at the end. For example:
sum = 0 ;
sound_value = 0 ;
for( int i2 = 0; i2 < SOUND_COUNT; i2++ )
{
soundRaw[i2] = analogRead( PIN_ANALOG_IN ) ;
sum += soundRaw[i2] ;
}
sound_value = sum / SOUND_COUNT ;
In this you do need to make sure that the data type forsum can accommodate a value of the maximum analogRead() return multiplied by SOUND_COUNT.
However you say that this is used for some sort of signal conditioning or processing of both a microphone and an accelerator. These devices have rather dissimilar bandwidth and dynamics, and it seems rather unlikely that the same filter would suit both. Applying robust DSP techniques such as IIR or FIR filters with suitably calculated coefficients would make a great deal more sense. You'd also need a suitable fixed sample rate that I am willing to bet is not achieved by simply reading the ADC in a loop with no specific timing

Configuring and limiting output of PI controller

I have implemented simple PI controller, code is as follows:
PI_controller() {
// handling input value and errors
previous_error = current_error;
current_error = 0 - input_value;
// PI regulation
P = current_error //P is proportional value
I += previous_error; //I is integral value
output = Kp*P + Ki*I; //Kp and Ki are coeficients
}
Input value is always between -π and +π.
Output value must be between -4000 and +4000.
My question is - how to configure and (most importantly) limit the PI controller properly.
Too much to comment but not a definitive answer. What is "a simple PI controller"? And "how long is a piece of string"? I don't see why you (effectively) code
P = (current_error = 0 - input_value);
which simply negates the error of -π to π. You then aggregate the error with
I += previous_error;
but haven't stated the cumulative error bounds, and then calculate
output = Kp*P + Ki*I;
which must be -4000 <= output <= 4000. So you are looking for values of Kp and Ki that keep you within bounds, or perhaps don't keep you within bounds except in average conditions.
I suggest an empirical solution. Try a series of runs, filing the results, stepping the values of Kp and Ki by 5 steps each, first from extreme neg to pos values. Limit the output as you stated, counting the number of results that break the limit.
Next, halve the range of one of Kp and Ki and make a further informed choice as to which one to limit. And so on. "Divide and conquer".
As to your requirement "how to limit the PI controller properly", are you sure that 4000 is the limit and not 4096 or even 4095?
if (output < -4000) output = -4000;
if (output > 4000) output = 4000;
To configure your Kp and Ki you really should analyze the frequency response of your system and design your PI to give the desired response. To simply limit the output decide if you need to freeze the integrator, or just limit the immediate output. I'd recommend freezing the integrator.
I_tmp = previous_error + I;
output_tmp = Kp*P + Ki*I_tmp;
if( output_tmp < -4000 )
{
output = -4000;
}
else if( output_tmp > 4000 )
{
output = 4000;
}
else
{
I = I_tmp;
output = output_tmp;
}
That's not a super elegant, vetted algorithm, but it gives you an idea.
If I understand your question correctly you are asking about anti windup for your integrator.
There are more clever ways to to it, but a simple
if ( abs (I) < x)
{
I += previous_error;
}
will prevent windup of the integrator.
Then you need to figure out x, Kp and Ki so that abs(x*Ki) + abs(3.14*Kp) < 4000
[edit] Off cause as macduff states, you first need to analyse your system and choose the korrect Ki and Kp, x is the only really free variable in the above equation.

31 bit limit on bit operations in R

I am trying to get around the 31-bit limit for bit operations in R. I can do this in pure R, but my issue is about implementing this in C for use in R.
Example
For example I have the data
> x = c(2147028898, 2147515013)
where each element is at most 32 bits, unsigned, and on which I'd like to do bit operations such as (but not limited to) (x >> 20) & 0xFFF. The end goal would be using many of these kinds of operations in a single function.
The two numbers are of different bit lengths.
> log2(x)
[1] 30.99969446331090239255 31.00002107107989246515
Normal bitwise operations in R yield the following result, ie NAs are introduced for the larger of the two.
> bitwShiftR(x,20)
[1] 2047 NA
Warning message:
In bitwShiftR(x, 20) : NAs introduced by coercion
> bitwAnd(x,20)
[1] 0 NA
Warning message:
In bitwAnd(x, 20) : NAs introduced by coercion
Workaround with R package 'bitops'
The bitopspackage does what I want, but my end goal is something more advanced, and I want to be able to use C, see below.
> library(bitops)
> bitShiftR(x,20)
[1] 2047 2048
I have looked at the C code for this package, but I don't really understand it. Does it have to be that complicated, or is that just for optimization for vectorized inputs and outputs?
Workaround in C (the issue)
My code is as follows, only a simple expression so far. I have tried different types in C, but to no avail.
#include <R.h>
void myBitOp(int *x, int *result) {
*result = (*x >> 20) & 0xFFF;
}
which I then compile with R CMD SHLIB myBitOp.c on a 64 bit machine.
$uname -a
Linux xxxxxxxxx 3.0.74-0.6.8-xen #1 SMP Wed May 15 07:26:33 UTC 2013 (5e244d7) x86_64 x86_64 x86_64 GNU/Linux
In R I load this with
> dyn.load("myBitOp.so")
> myBitOp <- function(x) .C("myBitOp", as.integer(x), as.integer(0))[[2]]
When I run the function I get back
> myBitOp(x[1])
[1] 2047
> myBitOp(x[2])
Error in myBitOp(x[2]) : NAs in foreign function call (arg 1)
In addition: Warning message:
In myBitOp(x[2]) : NAs introduced by coercion
So the question is, why do I get these NAs with this C code, and how do I fix it? The return value will always be much less than 31 bits btw.
Thank you!
Update
After studying the bitops code a bit more, and going through this presentation among other links I came up with this code (bonus vectorization here)
#include <R.h>
#include <Rdefines.h>
SEXP myBitOp(SEXP x) {
PROTECT (x = AS_NUMERIC(x) ) ;
double *xx = NUMERIC_POINTER(x);
SEXP result = PROTECT(NEW_NUMERIC(length(x)));
double *xresult = NUMERIC_POINTER(result);
for( int i=0; i < length(x); i++) {
xresult[i] = (double) ((((unsigned int) xx[i]) >> 20) & 0xFFF);
}
UNPROTECT(2);
return(result);
}
Compile with R CMD SHLIB myBitOp.c
And in R:
> dyn.load("myBitOp.so")
> myBitOp <- function(x) .Call("myBitOp", x)
> myBitOp(x)
[1] 2047 2048
I don't fully understand why or how yet, but it works, well seems to work for this example at least.
The second element of as.integer(x) will be NA because it's larger than .Machine$integer.max. NAOK = FALSE in your call to .C, so that NA in your input results in an error. Your call to .C will "succeed" if you set NAOK = TRUE (because, in this case, NA is technically NA_integer_, which is a special int value in C).
You'll have to be creative to get around this. You could try splitting values > 2^31-1 into two values, pass both of them to C, convert them to unsigned integers, sum them, convert the result to a signed integer, then pass back to R.

zero padding a signal in MATLAB

I have an audio signal of length 12769. I'm trying to perform STFT on it by breaking it into small windows of 1024 samples. This gives me with 12 exact windows while there are 481 points remaining. Since i need 543 (1024 - 481) more points to make up 1024 samples, i used the following code to zero pad.
f = [a zeros(1,542)];
where a is the audio file.
However i get an error saying
??? Error using ==> horzcat
CAT arguments dimensions are not consistent.
How can I overcome this?
Your vector a is a column vector and cannot be concatenated with row vector zeros(1,542). Use zeros(542,1) instead.
However, it is much easier to just use
f = a;
f(1024*ceil(end/1024)) = 0;
MATLAB will zero pad the vector up to element 1024, and it is independent of the array being column or row.
You can either remove the excess 481 samples using
Total_Samples = length(a);
for i=1 : Total_Samples-481
a_new[i] = a[i];
or you could add an additional 543 Zero samples by using
Total_Samples = length(a);
for i=Total_Samples+1 : Total_Samples+543
a[i] = 0 ;

Understanding Matlab code

I've got some code, and I've been trying to make some minor tweaks to it. It used to use fgets to load in a single character from a line, and use it to colour points in a 3D plot. So it would read
a
p
p
n
c
and then use other data files to assign what x, y, z points to give these. The result is a really pretty 3D plot.
I've edited the input file so it reads
0
1
1
0
2
2
0
and I want it to colour numbers the same colour.
This is where I've gotten so far with the code:
function PlotCluster(mcStep)
clear all
filename = input('Please enter filename: ', 's');
disp('Loading hopping site coordinates ...')
load x.dat
load y.dat
load z.dat
temp = z;
z = x;
x = temp;
n_sites = length(x);
disp('Loading hopping site types ...')
fp = fopen([filename]);
data = load(filename); %# Load the data
% Plot the devices
% ----------------
disp('Plotting the sample surface ...')
figure
disp('Hello world!')
ia = data == 0;
in = data == 1;
ip = data == 2;
disp('Hello Again')
plot3(x(ia),y(ia),z(ia),'b.') %,'MarkerSize',4)
hold on
plot3(x(ic),y(ic),z(ic),'b.') %,'MarkerSize',4)
plot3(x(in),y(in),z(in),'g.') %,'MarkerSize',4)
plot3(x(ip),y(ip),z(ip),'r.') %,'MarkerSize',4)
daspect([1 1 1])
set(gca,'Projection','Perspective')
set(gca,'FontSize',16)
axis tight
xlabel('z (nm)','FontSize',18)
ylabel('y (nm)','FontSize',18)
zlabel('x (nm)','FontSize',18)
%title(['Metropolis Monte Carlo step ' num2str(mcStep)])
view([126.5 23])
My issue is I'm getting this error
Index exceeds matrix dimensions.
Error in PlotCluster (line 34)
plot3(x(ia),y(ia),z(ia),'b.') %,'MarkerSize',4)
And I don't see why ia would go out of bounds of the x array. Is it to do with changing the fgets to a load statement? It was the only way to get it read the correct numbers in (not 49s and 50s which was very odd.)
The main bits that are sticking me are these lines (where the number used to correspond to 'a','n','p' etc)
ia = data == 0;
in = data == 1;
ip = data == 2;
They look like implied if statements with assignment from data to ia etc. where ia becomes an array. But I'm not sure.
Any help understanding this would be greatly appreciated.
I've fixed the issue, I hadn't updated my input correctly. To clear this up for anyone who comes to this question: ia = data ==0 means 'Make an array the same size as data, and fill it with 1 or 0 depending on if the logic (data == 0) is true or false'

Resources