Closed N-HEDGER closed 3 years ago
Hi Nick! Really awesome stuff here, sorry for the late reply. One way to keep some parameters fixed in iterative fit while fitting the others is to use the Bounds argument of python optimizers. When an optimizer is given a bound for a parameter where lower and upper bounds are identical like (1,1), it will just keep that parameter fixed to 1. I do this in the context of some pRF models. In my head, that is stylistically better than removing some parameters from the array, but in practice the latter might work better. Whatever works works :)
Let know when you are done coding and testing this branch, and we should indeed start merging it into the master.
Merged today! on the to do list, as from my comment above: Because it is something that is useful in a variety of situations, I will implement myself ASAP a minimal way to keep certain parameters fixed in iterative fitting to a specific value, and only fit others, without changing the structure of fitting params array (which could create problems later on) or using additional non-array structures (dictionaries). See the relevant issue that I opened
Here I have written some initial code to start incorporating connective fields into prfpy. This is based on previous discussions with TK and MA. You can see test/develop/CF_progress for a demo.
Summary (also detailed in commit messages).
As suggested, I have now separated out the pycortex-related stuff required for making the subsurfaces and distance matrices. This now sits in utils.py. There is a 'subsurface' class that can make the source subsurfaces for a pycortex subject. All of my pycortex-based visualisation stuff has also now gone.
As suggested, the distance matrices are now padded, so that distances in the opposite hemisphere are coded as np.inf. This prevents us having to treat the hemispheres separately, as was the case in my previous effort.
I created new stimulus and model classes, these are significantly more minimal than they were before and are structured similarly to the existing classes. The CFStimulus class only requires i) the data, ii) the vertex indices defining the subsurface and iii) the distance X distance matrices. Therefore, it is up to the user whether they want to use the 'subsurface' class in utils.py to provide this information or not. In principle, all the relevant information that is provided to the CFstimulus class could be created outside of pycortex - there is no requirement to use it.
At the fitting stage, things start to diverge a little. As discussed before, we may not always want to do a full GLM-based fitting for the CF models - we may want to use a fast method based on the dot product of z-scored data as used in Tomas' paper. Therefore, I include a quick_grid_fit method that does all the fitting via np.tensordot. This returns an array called quick_gridsearch_params to differentiate them from the gridsearch_params produced by grid_fit.
Currently, as far as I can tell, the current cross validation methods only work on the iterative search params - but if you want to use this 'quick' method, you would want to do the cross validation instead based on the gridsearch params. Hence, I have included a 'quick_xval' method.
In returning the best fitting parameters, note that the vertex centres should be ints - and keeping them in an array with the other parameters seems to force them into a float. Therefore, I additionally return the vertex_centres as a vector of ints.
To do list
One other alternative we discussed was to somehow use iterate over the distance matrix instead. At any rate, it is worth discussing the best way to do this.