Thanks very much! That should solve it. <br><br>J<br><br>2009/8/22  &lt;<a href="mailto:pkg-exppsy-pymvpa-request@lists.alioth.debian.org">pkg-exppsy-pymvpa-request@lists.alioth.debian.org</a>&gt;:<br>&gt; Send Pkg-ExpPsy-PyMVPA mailing list submissions to<br>
&gt;        <a href="mailto:pkg-exppsy-pymvpa@lists.alioth.debian.org">pkg-exppsy-pymvpa@lists.alioth.debian.org</a><br>&gt;<br>&gt; To subscribe or unsubscribe via the World Wide Web, visit<br>&gt;        <a href="http://lists.alioth.debian.org/mailman/listinfo/pkg-exppsy-pymvpa">http://lists.alioth.debian.org/mailman/listinfo/pkg-exppsy-pymvpa</a><br>
&gt; or, via email, send a message with subject or body &#39;help&#39; to<br>&gt;        <a href="mailto:pkg-exppsy-pymvpa-request@lists.alioth.debian.org">pkg-exppsy-pymvpa-request@lists.alioth.debian.org</a><br>&gt;<br>
&gt; You can reach the person managing the list at<br>&gt;        <a href="mailto:pkg-exppsy-pymvpa-owner@lists.alioth.debian.org">pkg-exppsy-pymvpa-owner@lists.alioth.debian.org</a><br>&gt;<br>&gt; When replying, please edit your Subject line so it is more specific<br>
&gt; than &quot;Re: Contents of Pkg-ExpPsy-PyMVPA digest...&quot;<br>&gt;<br>&gt;<br>&gt; Today&#39;s Topics:<br>&gt;<br>&gt;   1. Re: Pkg-ExpPsy-PyMVPA Digest, Vol 18, Issue 10 (Johan Carlin)<br>&gt;   2. Re: Pkg-ExpPsy-PyMVPA Digest, Vol 18, Issue 10<br>
&gt;      (Yaroslav Halchenko)<br>&gt;<br>&gt;<br>&gt; ----------------------------------------------------------------------<br>&gt;<br>&gt; Message: 1<br>&gt; Date: Fri, 21 Aug 2009 14:34:01 +0100<br>&gt; From: Johan Carlin &lt;<a href="mailto:jdc55@cam.ac.uk">jdc55@cam.ac.uk</a>&gt;<br>
&gt; Subject: Re: [pymvpa] Pkg-ExpPsy-PyMVPA Digest, Vol 18, Issue 10<br>&gt; To: <a href="mailto:pkg-exppsy-pymvpa@lists.alioth.debian.org">pkg-exppsy-pymvpa@lists.alioth.debian.org</a><br>&gt; Message-ID:<br>&gt;        &lt;<a href="mailto:7cd5a6280908210634p3100be7esf968c4a271326ce3@mail.gmail.com">7cd5a6280908210634p3100be7esf968c4a271326ce3@mail.gmail.com</a>&gt;<br>
&gt; Content-Type: text/plain; charset=ISO-8859-1<br>&gt;<br>&gt; Hi Yaro,<br>&gt;<br>&gt; I should probably have provided more context. :) Sorry about that.<br>&gt;<br>&gt; I have a number of coordinates of interest, where I want to plonk down<br>
&gt; a spherical ROI. I define my ROI like this:<br>&gt;<br>&gt; def make_spherical_ROI(ds,coords,radius=10):<br>&gt;    &#39;&#39;&#39;Returns a copy of the dataset which is masked to only<br>&gt;    include voxels within the sphere defined by coords.&#39;&#39;&#39;<br>
&gt;    coords.reverse() # Pynifti uses ZYX<br>&gt;    centre = ds.mapper.getOutId(coords)<br>&gt;    feats = ds.mapper.getNeighbors(centre,radius=radius)<br>&gt;    roi_ds = ds.copy()<br>&gt;    roi_ds = roi_ds.selectFeatures(feats)<br>
&gt;    return roi_ds<br>&gt;<br>&gt; Which seems similar to what you&#39;re suggesting. The problem with doing<br>&gt; this on masked data is that you get an error whenever the center<br>&gt; coordinate is outside the mask (even if the sphere contains other<br>
&gt; in-mask voxels). To get around this, I make the ROI based on unmasked<br>&gt; data, and then I apply the mask to the ROI dataset.<br>&gt;<br>&gt;&gt; ?also why do you want to invert the mapping with<br>&gt;&gt;<br>&gt;&gt;&gt; ? ? lmap = dict(zip(ds.labels_map.values(),ds.labels_map.keys()))<br>
&gt;&gt; whenever creating a new dataset? (may be I got confused...)<br>&gt;<br>&gt; If you just put in the ds.labels_map as it is, you get something like this:<br>&gt;<br>&gt; m_ds = MaskedDataset(samples=ds.samples_original, labels=ds.L,<br>
&gt; chunks=ds.C, labels_map=ds.labels_map)<br>&gt;<br>&gt; ValueError: Provided labels_map {&#39;212&#39;: 5, &#39;211&#39;: 4, &#39;121&#39;: 2, &#39;122&#39;:<br>&gt; 3, &#39;111&#39;: 0, &#39;112&#39;: 1, &#39;222&#39;: 7, &#39;221&#39;: 6} is insufficient to map all<br>
&gt; the labels. Mapping for label 5 is missing<br>&gt;<br>&gt; The 3-digit stringed values are my original labels. So it looks like<br>&gt; the ds.labels_map is stored with key=original label, value=mapped<br>&gt; label, but the opposite structure is needed when definining a new<br>
&gt; dataset.<br>&gt;<br>&gt;&gt; in your code instead of MaskedDataset you could use NiftiDataset where<br>&gt;&gt; samples... but before getting in details lets first figure out if above snippet<br>&gt;&gt; was what you were looking for<br>
&gt;<br>&gt; That sounds very useful, please tell me more. :)<br>&gt;<br>&gt; Cheers,<br>&gt;<br>&gt; Johan<br>&gt;<br>&gt;<br>&gt;<br>&gt; ------------------------------<br>&gt;<br>&gt; Message: 2<br>&gt; Date: Fri, 21 Aug 2009 16:27:28 -0400<br>
&gt; From: Yaroslav Halchenko &lt;<a href="mailto:debian@onerussian.com">debian@onerussian.com</a>&gt;<br>&gt; Subject: Re: [pymvpa] Pkg-ExpPsy-PyMVPA Digest, Vol 18, Issue 10<br>&gt; To: <a href="mailto:pkg-exppsy-pymvpa@lists.alioth.debian.org">pkg-exppsy-pymvpa@lists.alioth.debian.org</a><br>
&gt; Message-ID: &lt;<a href="mailto:20090821202728.GV24090@onerussian.com">20090821202728.GV24090@onerussian.com</a>&gt;<br>&gt; Content-Type: text/plain; charset=koi8-r<br>&gt;<br>&gt;<br>&gt; On Fri, 21 Aug 2009, Johan Carlin wrote:<br>
&gt;<br>&gt; just a quick hint:<br>&gt;&gt;     roi_ds = ds.copy()<br>&gt;&gt;     roi_ds = roi_ds.selectFeatures(feats)<br>&gt; imho there is no need for .copy() since selectFeatures creates a new<br>&gt; dataset anyways... or am I wrong? ;)<br>
&gt;<br>&gt;&gt; Which seems similar to what you&#39;re suggesting.<br>&gt; seems to be ;)<br>&gt;<br>&gt;&gt; The problem with doing<br>&gt;&gt; this on masked data is that you get an error whenever the center<br>&gt;&gt; coordinate is outside the mask (even if the sphere contains other<br>
&gt;&gt; in-mask voxels).<br>&gt; rright -- it seems we did not foresee such usecase, or just we were<br>&gt; wrong in our assumptions of its usefulness ;)<br>&gt;<br>&gt;&gt; To get around this, I make the ROI based on unmasked<br>
&gt;&gt; data, and then I apply the mask to the ROI dataset.<br>&gt; makes sense... I might suggest alternative solution (not sure if we<br>&gt; should implement a helper for it within pymvpa).<br>&gt;<br>&gt; So, if you load a single full (or ROI-surround mask, or just<br>
&gt; full-brain) volume (lets load it into dataset ds_full), and then<br>&gt; you load your ROI dataset within ds_roi, then for voxel  which is<br>&gt; outside of ROI but has features within sphere in the ROI you could use<br>
&gt; ds_full.mapper to figure out 3D coordinates for the neighbors, and then<br>&gt; just select the ones which are valid for ds_roi. Here is  a snippet<br>&gt; which I&#39;ve added to unittests (resides under<br>&gt; mvpa.tests.test_niftidataset:NiftiDatasetTests.testNiftiDatasetROIMaskNeighbors)<br>
&gt;<br>&gt;        ids_out = []<br>&gt;        for id_in in ds_full.mapper.getNeighborIn( (12, 20, 37), radius=20):<br>&gt;            try:<br>&gt;                ids_out.append(ds_roi.mapper.getOutId(id_in))<br>&gt;            except ValueError:<br>
&gt;                pass<br>&gt;<br>&gt; so, at the end in ids_out you got list of feature ids within ds_roi which<br>&gt; are within 20mm of that voxel... may be there is even better way -- but<br>&gt; don&#39;t have it in mind atm ;)<br>
&gt;<br>&gt; is that smth like what you need? ;)<br>&gt;<br>&gt;&gt; &gt;&gt; ? ? lmap = dict(zip(ds.labels_map.values(),ds.labels_map.keys()))<br>&gt;&gt; &gt; whenever creating a new dataset? (may be I got confused...)<br>
&gt;&gt; If you just put in the ds.labels_map as it is, you get something like this:<br>&gt;&gt; m_ds = MaskedDataset(samples=ds.samples_original, labels=ds.L,<br>&gt;&gt; chunks=ds.C, labels_map=ds.labels_map)<br>&gt;<br>
&gt;&gt; ValueError: Provided labels_map {&#39;212&#39;: 5, &#39;211&#39;: 4, &#39;121&#39;: 2, &#39;122&#39;:<br>&gt;&gt; 3, &#39;111&#39;: 0, &#39;112&#39;: 1, &#39;222&#39;: 7, &#39;221&#39;: 6} is insufficient to map all<br>
&gt;&gt; the labels. Mapping for label 5 is missing<br>&gt;<br>&gt;&gt; The 3-digit stringed values are my original labels. So it looks like<br>&gt;&gt; the ds.labels_map is stored with key=original label, value=mapped<br>
&gt;&gt; label, but the opposite structure is needed when definining a new<br>&gt;&gt; dataset.<br>&gt; I see it now ;) Sorry for too much &quot;magic&quot; behind  labels_map.<br>&gt;<br>&gt; Since it had evolved over time, docstring was not reflecting<br>
&gt; actual behavior I guess, so I adjusted docstring to be:<br>&gt;<br>&gt;            Map original labels into numeric labels.  If True, the<br>&gt;            mapping is computed if labels are literal.  If is False,<br>
&gt;            no mapping is computed. If dict instance -- provided<br>&gt;            mapping is verified and applied.<br>&gt;<br>&gt; So, what was happening -- since your labels are numeric already and you<br>&gt; provided original labels_map as dict, it tried to remap already numeric labels<br>
&gt; using mapping of literal to numeric. Obviously it failed ;)  With your<br>&gt; &#39;reverse&#39; mapping it has done somewhat more evil thing, mapped numerical labels<br>&gt; back into literal (which is not strictly forbidden, but I guess worth a<br>
&gt; warning, I&#39;ve added it -- ie, if now resultant labels are literal).<br>&gt;<br>&gt; After such mapping, some classifiers (which remap labels internally anyways,<br>&gt; such as SMLR, or just don&#39;t care much about type of labels, such as kNN I<br>
&gt; believe) might still perform as fine, but YMMV ;)<br>&gt;<br>&gt; back to your issue, to at least document a &#39;workaround&#39; whenever labels_map<br>&gt; should not be provided to constructor but rather assigned later on, I&#39;ve<br>
&gt; added another piece of documentation to labels_map keyword argument:<br>&gt;<br>&gt;  If you want to have labels_map just be present given already<br>&gt;  numeric labels, just assign labels_map dictionary to existing dataset<br>
&gt;  instance<br>&gt;<br>&gt; so, just define m_ds without providing labels_map argument, and then<br>&gt; assign it afterwards:<br>&gt;<br>&gt; m_ds.labels_map = ds.labels_map<br>&gt;<br>&gt;&gt; &gt; in your code instead of MaskedDataset you could use NiftiDataset where<br>
&gt;&gt; &gt; samples... but before getting in details lets first figure out if above snippet<br>&gt;&gt; &gt; was what you were looking for<br>&gt;&gt; That sounds very useful, please tell me more. :)<br>&gt;<br>&gt; Well... I guess with the above getIn/getOut magic you could simply work on<br>
&gt; NiftiDatasets as is, without reverting to MaskedDataset ;)<br>&gt;<br>&gt; in general, if your original space of MaskedDataset is actually the same<br>&gt; as NiftiDataset but used mask was different, you could simply<br>
&gt; construct a new NiftiImage using header information only from existing<br>&gt; NiftiDataset... smth like<br>&gt;<br>&gt; NiftiImage(maskeddataset.O, header=niftidataset.niftihdr).save(&#39;bugi.nii.gz&#39;)<br>&gt;<br>
&gt; --<br>&gt;                                  .-.<br>&gt; =------------------------------   /v\  ----------------------------=<br>&gt; Keep in touch                    // \\     (yoh@|www.)<a href="http://onerussian.com">onerussian.com</a><br>
&gt; Yaroslav Halchenko              /(   )\               ICQ#: 60653192<br>&gt;                   Linux User    ^^-^^    [175555]<br>&gt;<br>&gt;<br>&gt;<br>&gt;<br>&gt;<br>&gt; ------------------------------<br>&gt;<br>
&gt; _______________________________________________<br>&gt; Pkg-ExpPsy-PyMVPA mailing list<br>&gt; <a href="mailto:Pkg-ExpPsy-PyMVPA@lists.alioth.debian.org">Pkg-ExpPsy-PyMVPA@lists.alioth.debian.org</a><br>&gt; <a href="http://lists.alioth.debian.org/mailman/listinfo/pkg-exppsy-pymvpa">http://lists.alioth.debian.org/mailman/listinfo/pkg-exppsy-pymvpa</a><br>
&gt;<br>&gt;<br>&gt; End of Pkg-ExpPsy-PyMVPA Digest, Vol 18, Issue 11<br>&gt; *************************************************<br>&gt;<br><br><br><br>-- <br>Johan Carlin<br>Graduate Student<br>MRC Cognition &amp; Brain Sciences Unit<br>
15 Chaucer Road<br>Cambridge CB2 7EF<br>UK<br><br><a href="mailto:johan.carlin@mrc-cbu.cam.ac.uk">johan.carlin@mrc-cbu.cam.ac.uk</a><br>+44 (0)1223 355294 ext 593<br><br>