Dear David and Jeff,

> Only if you were going apply some sort of transformation that did not extend 
> globally

Exactly, this is why the LPCM package is great, as it assigns points
to parts of a curve.

I think I pretty much got what I need - it is not perfect yet but it
should be enough to give you an idea of what I was trying to achieve.

All the best,

Emmanuel


### Example ###
library(LPCM)
tmp=rnorm(2000)
X.1 = 5+tmp
Y.1 = 5+ (5*tmp+rnorm(2000))
tmp=rnorm(1000)
X.2 = 9+tmp
Y.2 = 40+ (1.5*tmp+rnorm(1000))
X.3 = 7+ 0.5*runif(500)
Y.3 = 15+20*runif(500)
Y = c(X.1,X.2,X.3)
X = c(Y.1,Y.2,Y.3)

lpc1 = lpc(cbind(X,Y), scaled=FALSE, h=c(1,1) , control=lpc.control(
boundary=1))
my.proj = lpc.spline(lpc1, project=TRUE, optimize=TRUE)

data = cbind( dist= my.proj$closest.pi, X1=lpc1$data[,1],
Y1=lpc1$data[,2], Xo=my.proj$closest.coords[,1],
Yo=my.proj$closest.coord[,2])
transfoData = matrix(apply(data, 1, function(x) { return( transfo(
(5+x[1])/10,x[2],x[3],x[4],x[5]))}), ncol=2, byrow=TRUE)

plot(transfoData)  ## This shows the result I'm looking for, not
perfect yet but it gives an idea.

###
### Moves a point from it's position to the new "normalized" position
###
transfo = function(dist, X1, Y1, X0, Y0) {
       # First, the point needs to be rotated
       trans=newCoord(X1, Y1, X0, Y0) ;
       Xnew=X1+trans[1]
       Ynew=Y1+trans[2]

       # second it is taken on the diagonal.
       Xfinal=dist
       Yfinal=dist
       X.TransToDiag = Xfinal-X0
       Y.TransToDiag = Yfinal-Y0
       return( c(Xnew+X.TransToDiag, Ynew+Y.TransToDiag))
}

## Rotates a point X1,Y1 relative to Xo,Yo
## The new point is either at 3pi/4 or 7pi/4 i.e., 90 degrees left or
## right of the diagonal.
##
newCoord = function(X1,Y1, Xo=0, Yo=0){

       # First calculates the coordinates of the point relative to Xo,Yo
       Xr = X1-Xo
       Yr = Y1-Yo

       # Now calculates the new coordinates,
       # i.e.,
       # if V is the vector defined from Xo,Yo to X1,Y1,
       # the new coordinates are such that Xf, Yf are at angle TETA
       # by default TETA=3*pi/4 or 135 degrees
       To = atan2(Yr,Xr)

       # XXX This is not perfect but will do the job for now
       if(Yr > Xr){
               TETA=3*pi/4
       } else {
               TETA=7*pi/4
       }
       Xn = Xr * (cos(TETA)/cos(To))
       Yn = Yr * (sin(TETA)/sin(To))

       # Xn, Yn are the new coordinates relative to Xo, Yo
       # However for the translation I need absolute coordinates
       # These are given by Xo + Xn and Y0 + Yn
       Xabs = Xo+Xn
       Yabs = Yo+Yn

       ## the translation that need to be applied to X1 and Y1 are thus:
       Xtrans = Xabs-X1
       Ytrans = Yabs-Y1
       return(c(Xtrans,Ytrans))
}







On 12 March 2012 20:58, David Winsemius <dwinsem...@comcast.net> wrote:
>
> On Mar 12, 2012, at 3:07 PM, Emmanuel Levy wrote:
>
>> Hi Jeff,
>>
>> Thanks for your reply and the example.
>>
>> I'm not sure if it could be applied to the problem I'm facing though,
>> for two reasons:
>>
>> (i) my understanding is that the inverse will associate a new Y
>> coordinate given an absolute X coordinate. However, in the case I'm
>> working on, the transformation that has to be applied depends on X
>> *and* on its position relative to the *normal* of the fitted curve.
>> This means, for instance, that both X and Y will change after
>> transformation.
>>
>> (ii) the fitted curve can be described by a spline, but I'm not sure
>> if inverse of such models can be inferred automatically (I don't know
>> anything about that).
>>
>> The procedure I envision is the following: treat the curve "segment by
>> segment", apply rotation+translation to each segment to bring it on
>> the
>> diagonal,
>
>
> That makes sense. Although the way I am imagining it would be to do a
> condition (on x) shift.
>
>
>> and apply the same transformation to all points
>> corresponding to the same segment (i.e., these are the points that are
>> close and within the "normal" area covered by the segment).
>>
>> Does this make sense?
>
>
> The first part sort of makes sense to me... maybe. You are thinking of some
> sort of local transformation that converts a curve to a straight line by
> rotation or deformation. Seems like a problem of finding a transformation of
> a scalar field. But you then want it extended outward to affect the regions
> at some distance from the curve. That's where might break down or at least
> becomes non-trivial. Because a region at a distance could be "in the sights"
> of the "normal" vector to the curve (not in the statistical sense but in the
> vector-field sense) of more than one segment of the curve. Only if you were
> going apply some sort of transformation that did not extend globally would
> you be able to do anything other than a y|x (y conditional on x) shift or
> expansion contraction
>
>> All the best,
>>
>> Emmanuel
>>
>>
>> On 12 March 2012 02:15, Jeff Newmiller <jdnew...@dcn.davis.ca.us> wrote:
>>>
>>> It is possible that I do not see what you mean, but it seems like the
>>> following code does what you want. The general version of this is likely to
>>> be rather more difficult to do, but in theory the inverse function seems
>>> like what you are trying to accomplish.
>>>
>>> x <- 1:20
>>> y <- x^2 + rnorm(20)
>>>
>>> y.lm <- lm( y ~ I(x^2) + x )
>>> plot( x, y )
>>> lines( x, predict( y.lm ) )
>>>
>>> qa <- coef(y.lm)["I(x^2)"]
>>> qb <- coef(y.lm)["x"]
>>> qc <- coef(y.lm)["(Intercept)"]
>>>
>>> # define inverse of known model
>>> f1 <- function( y ) { ( sqrt( 4*qa*( y -qc ) + qb^2 ) - qb ) / ( 2*qa ) }
>>> f2 <- function( y ) { -( sqrt( 4*qa*( y -qc ) + qb^2 ) + qb ) / ( 2*qa )
>>> }
>>>
>>> plot( x, f1( y ) )
>>>
>>>
>>>
>>> ---------------------------------------------------------------------------
>>> Jeff Newmiller                        The     .....       .....  Go
>>> Live...
>>> DCN:<jdnew...@dcn.davis.ca.us>        Basics: ##.#.       ##.#.  Live
>>> Go...
>>>                                     Live:   OO#.. Dead: OO#..  Playing
>>> Research Engineer (Solar/Batteries            O.O#.       #.O#.  with
>>> /Software/Embedded Controllers)               .OO#.       .OO#.
>>>  rocks...1k
>>>
>>> ---------------------------------------------------------------------------
>>> Sent from my phone. Please excuse my brevity.
>>>
>>>
>>>
>>> Emmanuel Levy <emmanuel.l...@gmail.com> wrote:
>>>
>>>> Dear Jeff,
>>>>
>>>> I'm sorry but I do not see what you mean. It'd be great if you could
>>>> let me know in more details what you mean whenever you can.
>>>>
>>>> Thanks,
>>>>
>>>> Emmanuel
>>>>
>>>>
>>>> On 12 March 2012 00:07, Jeff Newmiller <jdnew...@dcn.davis.ca.us>
>>>> wrote:
>>>>>
>>>>> Aren't you just reinventing the inverse of a function?
>>>>>
>>>>
>>>> ---------------------------------------------------------------------------
>>>>>
>>>>> Jeff Newmiller                        The     .....       .....  Go
>>>>
>>>> Live...
>>>>>
>>>>> DCN:<jdnew...@dcn.davis.ca.us>        Basics: ##.#.       ##.#.  Live
>>>>
>>>> Go...
>>>>>
>>>>>                                     Live:   OO#.. Dead: OO#..
>>>>
>>>>  Playing
>>>>>
>>>>> Research Engineer (Solar/Batteries            O.O#.       #.O#.  with
>>>>> /Software/Embedded Controllers)               .OO#.       .OO#.
>>>>
>>>>  rocks...1k
>>>>>
>>>>>
>>>>
>>>> ---------------------------------------------------------------------------
>>>>>
>>>>> Sent from my phone. Please excuse my brevity.
>>>>>
>>>>> Emmanuel Levy <emmanuel.l...@gmail.com> wrote:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> I am trying to normalize some data. First I fitted a principal curve
>>>>>> (using the LCPM package), but now I would like to apply a
>>>>>> transformation so that the curve becomes a "straight diagonal line"
>>>>
>>>> on
>>>>>>
>>>>>> the plot.  The data used to fit the curve would then be normalized by
>>>>>> applying the same transformation to it.
>>>>>>
>>>>>> A simple solution could be to apply translations only (e.g., as done
>>>>>> after a fit using loess), but here rotations would have to be applied
>>>>>> as well. One could visualize this as the "stretching of a curve",
>>>>>> i.e., during such an "unfolding" process, both translations and
>>>>>> rotations would need to be applied.
>>>>>>
>>>>>> Before I embark on this (which would require me remembering long
>>>>>> forgotten geometry principles) I was wondering if you can think of
>>>>>> packages or tricks that could make my life simpler?
>>>>>>
>>>>>> Thanks for any input,
>>>>>>
>>>>>> Emmanuel
>>>>>>
>>>>>>
>>>>>> Below I provide an example - the black curve is to be "brought" along
>>>>>> the diagonal, and all data points normal to a "small segment" (of the
>>>>>> black curve) would undergo the same transformation as it - what
>>>>>> "small" is remains to be defined though.
>>>>>>
>>>>>>   tmp=rnorm(2000)
>>>>>>   X.1 = 5+tmp
>>>>>>   Y.1 = 5+ (5*tmp+rnorm(2000))
>>>>>>   tmp=rnorm(1000)
>>>>>>   X.2 = 9+tmp
>>>>>>   Y.2 = 40+ (1.5*tmp+rnorm(1000))
>>>>>>   X.3 = 7+ 0.5*runif(500)
>>>>>>   Y.3 = 15+20*runif(500)
>>>>>>   X = c(X.1,X.2,X.3)
>>>>>>   Y = c(Y.1,Y.2,Y.3)
>>>>>>
>>>>>>   lpc1 = lpc(cbind(X,Y), scaled=FALSE, h=c(1,1) )
>>>>>>   plot(lpc1)
>>>>>>
>>>>>> ______________________________________________
>>>>>> R-help@r-project.org mailing list
>>>>>> https://stat.ethz.ch/mailman/listinfo/r-help
>>>>>> PLEASE do read the posting guide
>>>>>> http://www.R-project.org/posting-guide.html
>>>>>> and provide commented, minimal, self-contained, reproducible code.
>>>>>
>>>>>
>>>
>>
>> ______________________________________________
>> R-help@r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide
>> http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.
>
>
> David Winsemius, MD
> West Hartford, CT
>

______________________________________________
R-help@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

Reply via email to