0todd0000 / spm1d

One-Dimensional Statistical Parametric Mapping in Python
GNU General Public License v3.0
63 stars 21 forks source link

Figures for multi-cluster SPM #28

Closed bernard-liew closed 9 years ago

bernard-liew commented 9 years ago

Dear Todd,

I like to inquire two things on printing figures for SPM. Sample code

ax3 = plt.subplot2grid((6,5), (4, 0), colspan=5)
vectors_ti[2].plot()
vectors_ti[2].plot_threshold_label(fontsize=10)
vectors_ti[2].plot_p_values(size=10, offsets=[(0,0.3)])
pyplot.title(titles[2])
pyplot.ylabel('SPM{F}')
pyplot.xlabel('Stance phase (%)')

If there are multiple clusters, this only prints the p values on one cluster. How can I get them to print all the clusters at the respective cluster position.

The critical threshold position, how can I offset its position, since it is often blocked by the pvalues or the graphs itself?

Regards, Bernard

0todd0000 commented 9 years ago

Hi Bernard,

Thanks for your question. The easiest way to customize text is to use pyplot.text; as you've noticed there are only rudimentary text options available in spm1d.

More specifically, after computing the test statistic and conducting inference like this:

t  = spm1d.stats.ttest2(yA, yB)
ti = t.inference(0.05)

You can plot the threshold in an arbitrary place like this:

pyplot.text(1, 3, '%.3f'%ti.zstar)

or you can recreate the spm1d threshold string using:

s = r'$\alpha$=0.05:  $t^*$=%.3f' %ti.zstar
pyplot.text(1, 3, s)

To plot cluster-specific p values you'll need the p values themselves and possibly also the cluster centroids. You can get those like this:

cluster = ti.clusters[0]  #first cluster
x,y = cluster.xy  #centroid
p = cluster.P #p value
pyplot.text(x+0.1, y+0.1, 'p = %.3f' %p )

There are currently no plans to improve the text options because it's too complicated to algorithmically avoid overlapping text when there are multiple axes/subplots in one figure and multiple clusters.

Regarding the problem of p values appearing for only one cluster: I think the problem is in this line:

vectors_ti[2].plot_p_values(size=10, offsets=[(0,0.3)])

There is only one offset provided, so only one cluster will be plotted. In other words, this would plot p values for two clusters (if two or more clusters exist):

ti.plot_p_values(size=10, offsets=[(0,0.3), (0,0.3)])

and this would plot p values for three clusters (if three or more clusters exist).

ti.plot_p_values(size=10, offsets=[(0,0.3), (0,0.3), (0,0.3)])

To apply a constant offset to all clusters use:

ti.plot_p_values(size=10, offsets=[(0,0.3)]*ti.nClusters)

Perhaps a keyword option like offset_all_clusters=(0,0.3) would be more intuitive? Please let me know if that would be helpful. If so I'll update the code and add an example to spm1d.org to document the usage of the "offset" functionality.

Cheers,

Todd

bernard-liew commented 9 years ago

Hi Todd,

that functionality is good. The code is good and would be good if it is included in spm1d. Many thanks for the help. It will be good to have some documentations on common figures, and common annotations used in your papers eg. including drawing arrows.

Kind Regards, Bernard

0todd0000 commented 9 years ago

Hi Bernard,

Please find that the "offset_all_clusters" functionality is now implemented and can be downloaded in version 0.3.1.2 of the software (now available on both github and pypi). An example use can be found in:

./spm1d/examples/stats1d/ex_ttest2.py

ti.plot_p_values(size=10, offset_all_clusters=(0,0.9))

Note that you'll now also receive a warning message when there are multiple clusters and you don't specify enough offsets. In the above example there are two clusters, so if you use:

ti.plot_p_values(size=10, offsets=[(0,0.1)])

You will see the following warning message:

WARNING:  there are fewer offsets than clusters.  To set offsets for all clusters use the offset_all_clusters keyword.

Thanks as well for your suggestions regarding plotting options, we'll try to create some examples in future documentation releases. In the meantime please refer to the matplotlib documentation for excellent examples of figure customization: http://matplotlib.org http://matplotlib.org/examples

Here are two examples on annotating figures with arrows: http://matplotlib.org/examples/units/annotate_with_units.html http://matplotlib.org/examples/pylab_examples/demo_annotation_box.html

Cheers,

Todd