Sarah
New Member
Posts: 31
|
Post by Sarah on Feb 7, 2018 20:43:22 GMT 8
Try this:
library(ProFit)
# make a test PSF and modellist with single point source testpsf=profitMakeGaussianPSF()
modellist=list( pointsource=list( xcen=5, ycen=5, mag=0 ) )
test1=profitMakeModel(modellist, psf=testpsf) # fails: # Error in profitMakeModel(modellist, psf = testpsf) : # VECTOR_ELT() can only be applied to a 'list', not a 'double'
# it works as soon as the modellist has at least 2 point sources (or any other profile) modellistnew=list( pointsource=list( xcen=c(5,10), ycen=c(5,10), mag=c(0,0) ) )
test2=profitMakeModel(modellistnew, psf=testpsf) # works fine
...why is that?
|
|
Sarah
New Member
Posts: 31
|
Post by Sarah on Feb 7, 2018 22:30:04 GMT 8
Ok, I traced it down a little more because it seems so odd:
The error occurs in profitMakeModel in the line: basemat = .Call("R_profit_make_model", model) because model$profiles$psf is a vector when there's only 1 pointsource, while it's a list in all other cases.
That in turn happens in the lines: for (name in names(modellist$pointsource)) { profiles[["psf"]][[name]] = c(unlist(modellist$pointsource[[name]][whichcomponents$pointsource])) } and as far as I can see it's down to the behaviour of lists. For example, try
testlist=list() testlist$psf[['xcen']]=c(5) # passing it just 1 element is.list(testlist$psf) # --> FALSE
testlist=list() testlist$psf[['xcen']]=c(5,10) # passing it 2 elements now is.list(testlist$psf) # --> TRUE
It works when using the $ sign instead, i.e. testlist=list() testlist$psf$xcen=c(5) is.list(testlist$psf) # --> TRUE as well
... which confuses me even more because I thought the $ sign and the double brackets were equivalent in R?
|
|
|
Post by rtobar on Feb 8, 2018 0:27:27 GMT 8
Hi Sarah,
You were pointing effectively in the right direction. Only to be clear, and I think you know this already, the "VECTOR_ELT() can only be applied to a 'list', not a 'double'" error referred to testlist$psf being a vector instead of a list, and not to testlist$psf$xcen. Also, as you discovered, the problem was triggered depending on how we initialized the inner xcen member. To be more specific, I think the actual problem is that we were implicitly creating the testlist$psf member when creating its $testlist$psf$xcen member. I don't know the rules to the detail, but I guess the runtime is left to guess what you actually meant testlist$psf to be in that case. I guess that would explain why depending on how you initialize the $xcen member you get a different object for $psf.
In terms of a solution, it's true that
testlist = list() testlist$psf$xcen = c(5)
works, ut in our case we cannot use it because the last member name (ie., 'xcen') is the value of a variable instead of a fixed string. It would also be better to be explicit about the initialization of $psf, which is what we will start doing now:
name = 'xcen' testlist = list() testlist$psf = list() testlist$psf[[name]] = c(5)
Cheers,
Rodrigo
|
|
Sarah
New Member
Posts: 31
|
Post by Sarah on Feb 8, 2018 1:08:34 GMT 8
Cool, thanks for the explanation! So the difference between the $ sign and the double brackets is that the $ sign specifies that the member is a list, while the double brackets leave it up for guesses? And then the guess depends on the type of object you pass it (i.e. single number vs. vector in our case) and so the different results arise, right? I'm aware that the $-version doesn't work in this particular case, but just trying to understand the difference. Do you know if the $ sign and double brackets make any difference when accessing existing elements (rather than creating new ones)?
|
|
|
Post by rtobar on Feb 8, 2018 8:34:59 GMT 8
Hi Sarah,
I'm not really an R expert, so I can only second you in your guessing about how the $ sign plays a role on defining the type of object its parent structure, but nor really confirm it. When accessing elements they both still seem to behave exactly the same, which is the normal behavior one would expect.
Just to be clear, the problem is not much on whether we are using $ or [[]], but the fact that the structure on which we are using it gets implicitly defined. If everything is well defined, normal rules seem to work as expected. What we were doing could have been undefined behavior, in which case the runtime is more or less free to do whatever it wants.
|
|
asgr
Junior Member

Posts: 56
|
Post by asgr on Feb 8, 2018 15:50:14 GMT 8
Hmm, yes, I think how type assumptions within lists get defined can be non-obvious. Within R it rarely matters because operations will work similar from the user's POV (multiply by 2 will work whether list, vector or scalar), and will all look the same when printed. I guess what broke is the pipe to C++, which is necessarily strict with typing. Rodrigo's fix was just to add one line explicitly setting the final type to list.
Aaron
|
|