<?xml version="1.0"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>sburns.org</title>
    <link>http://sburns.org/</link>
    <atom:link href="http://sburns.org/rss.xml" rel="self" type="application/rss+xml" />
    <description>All Posts</description>
    <language>en-us</language>
    <pubDate>Mon, 11 Feb 2019 13:35:38 UTC</pubDate>
    <lastBuildDate>Mon, 11 Feb 2019 13:35:38 UTC</lastBuildDate>
    
      <item>
        <title>Miscellaneous Thoughts on the Academic STEM Brain Drain or, How I Learned to Stop Worrying and Leave The Lab</title>
        <link>http://sburns.org/2014/07/10/brain-drain.html</link>
        <pubDate>Thu, 10 Jul 2014 00:00:00 UTC</pubDate>
        <author></author>
        <guid>http://sburns.org/2014/07/10/brain-drain.html</guid>
        <description>&lt;p&gt;&lt;a href=&quot;http://jakevdp.github.io/blog/2013/10/26/big-data-brain-drain/&quot;&gt;Many&lt;/a&gt; &lt;a href=&quot;http://andy.terrel.us/blog/2013/11/21/joining-big-data-brain-drain/&quot;&gt;smart&lt;/a&gt; &lt;a href=&quot;http://anothersb.blogspot.com/2014/02/goodbye-academia.html&quot;&gt;people&lt;/a&gt; have written pieces related to the academic brain drain. Please read the originals but they boil down to these ideas:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;“Big Science” requires computational skills more lucratively rewarded in industry.&lt;/li&gt;
  &lt;li&gt;The current (read: abysmal, with no signs of improvement) funding situation requires scientists to devote an increasing proportion of their time to secure funding. Scientists get up in the morning hoping to explain the world, not write grants.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having spent the better part of a decade in some kind of academic research role and with tomorrow my last day at Vanderbilt, here are some (&lt;a href=&quot;http://twitter.com/fonnesbeck/status/473587937763135488&quot;&gt;required?&lt;/a&gt;) thoughts about the brain drain.&lt;/p&gt;

&lt;h3 id=&quot;engineering-is-not-science&quot;&gt;Engineering is not Science&lt;/h3&gt;

&lt;p&gt;My past research interests, especially neuroimaging, are computationally intensive. Not only are data storage and compute time for analyses high but the need to verify the computer is doing what you think (and publish!) is vital. This last part translates to writing both well-architected &amp;amp; correct software for analysis. This requires building codebases not at all once but rather through a controlled, deliberate and iterative fashion. Eventually people working in the computing-oriented sciences quickly have a solid if not expert knowledge of modern computing systems from the OS up through their application layers.&lt;/p&gt;

&lt;p&gt;This process of software engineering has become ever more fascinating to me. In an effort to produce both state-of-the-art and reproducible scienctific workflows, I’m continually searching for resources in the hope of applying sound software engineering principles to the generation of good science. However, deliberately engineering good science is not the same as scientific output and that output alone is the differentiator between a successful academic scientist and a struggling grad student/adjunct faculty member.&lt;/p&gt;

&lt;p&gt;Increasingly, universities care about the securing of funding (in no small part to pay for explosive otherwise-unrelated-to-research staff growth) and funding is generally routed to the testing of new hypotheses, not engineering better infrastructure to more efficiently run current projects.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Code_refactoring&quot;&gt;Refactoring&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/Unit-testing&quot;&gt;unit-testing&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/Version_control&quot;&gt;version-control&lt;/a&gt;, pillars of professional software engineering, have little place in an environment where only results and not the &lt;em&gt;maintainability&lt;/em&gt; of those results matter. I not only agree that computational skills nurtured in science education are more lucratively rewarded in industry, but that &lt;strong&gt;academia is a caustic environment to improve one’s software engineering ability&lt;/strong&gt;.  If you’re an engineer rather than scientist at heart, academia is a tough place to practice your trade.&lt;/p&gt;

&lt;h3 id=&quot;academic-classism&quot;&gt;Academic Classism&lt;/h3&gt;

&lt;p&gt;There is a very real class war in academia penalizing those who forego the traditional undergrad-grad school-postdoc-tenure track faculty path. To a fault, I tend to get bored easily (see my desire above to constantly make existing things better) and I am positive that if I entered a Ph.D. program (assuming I could find one enough appealing), after five years I would have 3-4 mostly-finished projects and none on their own would lead to a dissertation.&lt;/p&gt;

&lt;p&gt;The successful completion of a Ph.D. requires hard work, perseverance and tenacity; I’m not complaining about that. My beef lies in the bias of Ph.D’s awarded to people who put their head down for 5 years and think about nothing else than their dissertation. I am not that person (especially now that I have a family) and I don’t think the skills required to complete a Ph.D. are necessarily required to be a good scientist. There is overlap but many good (or would-be) scientists don’t have the mindset to complete a Ph.D.&lt;/p&gt;

&lt;p&gt;Herein lies the issue—in the university setting, people without a Ph.D. carry little to no political capital. They cannot run departments, hold tenure or execute their own research program. Perhaps the skills to successfully command these posts are fostered during Ph.D. work (I wouldn’t know). Without your Ph.D. you can’t be faculty and that makes you less useful in the eyes of the university because it’s much more difficult to generate income without a research or clinical program of your own. The staff designation places an upper bound on both career trajectory and compensation.&lt;/p&gt;

&lt;p&gt;I find common threads between this and &lt;a href=&quot;http://www.npr.org/blogs/alltechconsidered/2014/02/06/272646267/how-the-meritocracy-myth-affects-women-in-technology&quot;&gt;the disheartening trend of meritocracy in tech&lt;/a&gt;. As a white male of privilege, in no way do I intend to diminish the struggle minorities face in STEM but it’s not difficult to find analogies in the implicit biases generated within both the tech and academic communities. Both operate under the auspices of “the cream will rise to the top” without considering the diversity, makeup and ingredients of the cream.&lt;/p&gt;

&lt;h3 id=&quot;random-thoughts&quot;&gt;Random Thoughts&lt;/h3&gt;

&lt;p&gt;I couldn’t congeal these into a narrative (not that there’s an underlying theme above!) and so in no particular order:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Universities face multiple, overlapping &lt;a href=&quot;http://en.m.wikipedia.org/wiki/Women_in_STEM_fields#Leaky_pipeline&quot;&gt;leaky pipelines&lt;/a&gt; due to many disparate internal and external forces.&lt;/li&gt;
  &lt;li&gt;Academia undervalues engineering talent. Said talent should no longer be afraid to leave academic jobs whose main advantage has always been stability. Current funding situations have removed or diminished this advantage.&lt;/li&gt;
  &lt;li&gt;Extremely smart people work in academia but university hiring practices (especially concerning little to no remote workforce) may diminish the chance for like-minded coworkers. I worked with brilliant people at all levels in Vanderbilt but very often felt like an orphan given my interests.&lt;/li&gt;
  &lt;li&gt;The need to write off capital depreciation for tax purposes may produce suboptimal computing environments in universities. I would much rather have deployed my bigger applications to EC2/Heroku/etc. but computing resources have to be spent on &lt;strong&gt;hard&lt;/strong&gt;ware. The need to own the hardware is silly.&lt;/li&gt;
  &lt;li&gt;Intellectual Property rights for staff at universities are generally not good. In particular, Vanderbilt considers books, papers &amp;amp; art to be  owned by the creator while software and technology is owned by the institution. I’d love to hear a lawyer explain the difference with a straight face.&lt;/li&gt;
  &lt;li&gt;At least at Vanderbilt, faculty are given nearly a day a week to consult on external projects without university interference. Any and all external collaborations I worked on were negotiated through the institution with no addition to my bottom line.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Universities will hold a monopoly on interesting ideas for the near future, at least until those ideas become profitable. The need to better improve myself became too great and the call to a new line of work too loud.&lt;/p&gt;

&lt;!--links--&gt;

</description>
      </item>
    
      <item>
        <title>Screencast for Motivation to use GitHub</title>
        <link>http://sburns.org/2014/05/30/github-screencast.html</link>
        <pubDate>Fri, 30 May 2014 00:00:00 UTC</pubDate>
        <author></author>
        <guid>http://sburns.org/2014/05/30/github-screencast.html</guid>
        <description>&lt;p&gt;I’m currently enrolled in &lt;a href=&quot;http://teaching.software-carpentry.org&quot;&gt;Software Carpentry’s&lt;/a&gt; Online Instructor Training and our most recent assignment was to make a 2-3 minute screencast to motivate the usage of a tool or idea one might cover in a Software Carpentry Bootcamp. I choose to do mine on GitHub.&lt;/p&gt;

&lt;iframe src=&quot;//player.vimeo.com/video/96844861&quot; width=&quot;500&quot; height=&quot;281&quot; frameborder=&quot;0&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;There are some things I don’t like about it (should have zoomed in on the browser as the editor &amp;amp; terminal become distracting, could have used some bullet points in the outro) but overall I’m happy with it.&lt;/p&gt;

&lt;p&gt;If you’re at all interested in leading a Software Carpentry Bootcamp, I highly recommend the Instructor Training. I’ve learned very interesting ways to approach teaching &amp;amp; evaluating what I’ve (hopefully) taught.&lt;/p&gt;

</description>
      </item>
    
      <item>
        <title>A Recipe for Cortical Tractography Using Freesufer Labels</title>
        <link>http://sburns.org/2014/05/03/cortical-tractography-recipe.html</link>
        <pubDate>Sat, 03 May 2014 00:00:00 UTC</pubDate>
        <author></author>
        <guid>http://sburns.org/2014/05/03/cortical-tractography-recipe.html</guid>
        <description>&lt;p&gt;In this post, I’m going to describe a method I’ve been working on for performing probabilistic tractography in a single subject using automatically generated cortical labels from Freesurfer. This isn’t new or groundbreaking, however the description of such methods as found in a paper is generally a lossy transmission of the &lt;strong&gt;actual code&lt;/strong&gt; used to generate this kind of analysis.&lt;/p&gt;

&lt;p&gt;Scientific replicability &amp;amp; reproducibility require a working implemention and I’ve not seen such a description of this kind of analysis &amp;amp; processing in the internet, hence this article. I hope this is helpful to the community. It’s also taken a lot of time for me to get here so hopefully you won’t have to make the same mistakes I have (but mistakes are good so hopefully you make your own :)&lt;/p&gt;

&lt;p&gt;I’m making certain assumptions &amp;amp; decisions in this analysis. If you don’t agree with them, that’s alright, you’re not going to hurt my feelings. It doesn’t make this any more or less correct. This is an immature technique and I don’t think there are hard &amp;amp; fast rules the field has yet approved for cortical tractography. But if you think something is &lt;strong&gt;really&lt;/strong&gt; wrong, I’d love to get your opinion, discuss it and potentially update this post.&lt;/p&gt;

&lt;p&gt;The goal of this analysis is to get a measure of structural connectivity between all cortical “regions” of the brain. There are an infinite amount of ways to divy up a brain into regions of interest. Here, I’m choosing to use the 2009 labels produced by Freesurfer Destrieux atlas. Using FSL’s &lt;code class=&quot;highlighter-rouge&quot;&gt;probtrackx2&lt;/code&gt; tool, we’ll use DTI data to perform “in-silico tractography” (hand-waving) from each region and measure to what degree each region “connects” to every other region. There are a lot of caveats in the above paragraph &amp;amp; a lot of underlying assumptions I’m making up-to-and-including:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Freesurfer generates accurate &amp;amp; reliable cortical labels from a clean T1 image.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Diffusion_MRI&quot;&gt;Diffusion MRI&lt;/a&gt; captures the relative motion of water molecules in tissue.&lt;/li&gt;
  &lt;li&gt;Water most likely moves parallel to axons which carry action potentials from the neuron to their target.&lt;/li&gt;
  &lt;li&gt;Action potentials are the primary means neurons use to communicate with one another.&lt;/li&gt;
  &lt;li&gt;During development, the brain organizes itself in such a way that groups of neurons that communicate often with other groups will develop large axonal bundles between one another.&lt;/li&gt;
  &lt;li&gt;These bundles restrict the diffusion of water in a way that is detectable during a diffusion MR sequence.&lt;/li&gt;
  &lt;li&gt;Using the diffusion information, we can build probability density functions at every voxel to describe our best guess at which way water flows at that particular voxel. These PDFs also help us characterize the uncertainty inherent in the measurement.&lt;/li&gt;
  &lt;li&gt;Using these PDFs, we can step through the diffusion image, generating the most likely path water would flow beginning at some point A. We call this a tract, streamline or sample.&lt;/li&gt;
  &lt;li&gt;Generating &lt;strong&gt;lots&lt;/strong&gt; of these potential tracts, we can make statistically sound inferences about whether we actually trust that the generated tracts represent the actual underlying anatomy. The actual anatoamy is otherwise difficult to attain from our subjects, hence why we’re imaging them.&lt;/li&gt;
  &lt;li&gt;Pulling this large amount of data together, we can generate a NxN connectivity matrix and plot the relative connectivity between all regions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If I haven’t offended you with any of these statements, let’s get on with it.&lt;/p&gt;

&lt;h3 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h3&gt;

&lt;h4 id=&quot;data&quot;&gt;Data&lt;/h4&gt;

&lt;p&gt;This analysis requires the following MR data:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A Freesurfer-able T1 image. This should cover the entire brain at high-resolution (~1mm&lt;sup&gt;3&lt;/sup&gt; voxels). For this article, I’m going to call this file &lt;code class=&quot;highlighter-rouge&quot;&gt;T1.nii.gz&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;A DTI sequence with at least 30 directions, though depending on your SnR fewer directions can be acceptable in certain cases. The standard sequence I use is 60 directions. I’m going to refer to this file as &lt;code class=&quot;highlighter-rouge&quot;&gt;dti.nii.gz&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The b-values &amp;amp; b-vectors for the gradients. These files should be generated in the process from converting your raw images (probably in DICOM format) to the standard research format (NIFTI). These are simple text files that I’ll refer to as &lt;code class=&quot;highlighter-rouge&quot;&gt;bvals&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;bvecs&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We’re going to call this subject &lt;code class=&quot;highlighter-rouge&quot;&gt;janedoe&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; ./
T1.nii.gz      dti.nii.gz         bvecs
bvals
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;software&quot;&gt;Software&lt;/h4&gt;

&lt;p&gt;I’ll be using &lt;a href=&quot;http://surfer.nmr.mgh.harvard.edu/fswiki/DownloadAndInstall&quot;&gt;Freesurfer&lt;/a&gt; &amp;amp; &lt;a href=&quot;http://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FslInstallation&quot;&gt;FSL&lt;/a&gt; for this analysis, both of which are freely available. In particular, I use Freesurfer 5.1 &amp;amp; FSL 5.0.6 though I’m fairly certain this will work in the newest version of Freesurfer, 5.3.&lt;/p&gt;

&lt;h3 id=&quot;structural-processing&quot;&gt;Structural processing&lt;/h3&gt;

&lt;p&gt;The T1 image needs to be processed through Freesurfer’s standard &lt;code class=&quot;highlighter-rouge&quot;&gt;recon-all&lt;/code&gt; pipeline. There are many resources for how to do this online, namely the &lt;a href=&quot;http://surfer.nmr.mgh.harvard.edu/fswiki&quot;&gt;Freesurfer wiki&lt;/a&gt;. I run the pipeline this way:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;recon-all &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; janedoe &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; T1.nii.gz
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;recon-all &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; janedoe &lt;span class=&quot;nt&quot;&gt;-all&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-qcache&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-measure&lt;/span&gt; thickness &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-measure&lt;/span&gt; curv &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-measure&lt;/span&gt; sulc &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-measure&lt;/span&gt; area &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-measure&lt;/span&gt; jacobian_white
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mri_annotation2label &lt;span class=&quot;nt&quot;&gt;--subject&lt;/span&gt; janedoe &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--hemi&lt;/span&gt; lh &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--annotation&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SUBJECTS_DIR&lt;/span&gt;/janedoe/label/lh.aparc.a2009s.annot &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--outdir&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SUBJECTS_DIR&lt;/span&gt;/janedoe/label &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--surface&lt;/span&gt; white
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mri_annotation2label &lt;span class=&quot;nt&quot;&gt;--subject&lt;/span&gt; janedoe &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--hemi&lt;/span&gt; rh &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--annotation&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SUBJECTS_DIR&lt;/span&gt;/janedoe/label/rh.aparc.a2009s.annot &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--outdir&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SUBJECTS_DIR&lt;/span&gt;/janedoe/label &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--surface&lt;/span&gt; white
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first &lt;code class=&quot;highlighter-rouge&quot;&gt;recon-all&lt;/code&gt; imports the data and creates the standard folder layout in &lt;code class=&quot;highlighter-rouge&quot;&gt;$SUBJECTS_DIR/janedoe&lt;/code&gt;. The second call executes all three steps of the Freesurfer pipeline (note the &lt;code class=&quot;highlighter-rouge&quot;&gt;-all&lt;/code&gt; flag). The two &lt;code class=&quot;highlighter-rouge&quot;&gt;mri_annotation2label&lt;/code&gt; commands convert the Destrieux cortical annotation to individual labels across the two hemispheres. These labels are written into the &lt;code class=&quot;highlighter-rouge&quot;&gt;label/&lt;/code&gt; directory for the subject. Labels are simple text files that map Freesufer vertices to particular cortical regions.&lt;/p&gt;

&lt;p&gt;This process usually takes between 20-40 hours depending on the quality of data. Grab a cup of coffee or a nap.&lt;/p&gt;

&lt;p&gt;After this completes, we need to do quality assurance. I’m sure there are more rigorous examples out there but this is what I do. For &lt;code class=&quot;highlighter-rouge&quot;&gt;janedoe&lt;/code&gt;, I generate the following tcl scripts:&lt;/p&gt;

&lt;div class=&quot;language-tcl highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cat janedoe.tkmedit.tcl
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; set i 5 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt; &amp;lt; 256 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; incr i 10 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
SetSlice &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;
RedrawScreen
SaveTIFF janedoe_screenshots/tkmedit-$i.tiff
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
$ cat janedoe.tksurfer.lh.tcl
make_lateral_view&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
redraw&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
save_tiff janedoe_screenshots/rh-lateral.tiff&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
rotate_brain_y 180&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
redraw&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
save_tiff janedoe_screenshots/rh-medial.tiff&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
labl_import_annotation aparc.a2009s.annot&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
redraw&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
make_lateral_view&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
redraw&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
save_tiff janedoe_screenshots/rh-annot-lateral.tiff&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
rotate_brain_y 180&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
redraw&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
save_tiff janedoe_screenshots/rh-annot-medial.tiff&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
$ cat janedoe.tksurfer.rh.tcl
make_lateral_view&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
redraw&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
save_tiff janedoe_screenshots/rh-lateral.tiff&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
rotate_brain_y 180&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
redraw&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
save_tiff janedoe_screenshots/rh-medial.tiff&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
labl_import_annotation aparc.a2009s.annot&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
redraw&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
make_lateral_view&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
redraw&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
save_tiff janedoe_screenshots/rh-annot-lateral.tiff&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
rotate_brain_y 180&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
redraw&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
save_tiff janedoe_screenshots/rh-annot-medial.tiff&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Given these files, I run the following commands:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mkdir &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; janedoe_screenshots
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;tkmedit janedoe brain.finalsurfs.mgz &lt;span class=&quot;nt&quot;&gt;-aseg&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-surfs&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-tcl&lt;/span&gt; ./janedoe.tkmedit.tcl
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;tksurfer janedoe lh inflated &lt;span class=&quot;nt&quot;&gt;-gray&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-tcl&lt;/span&gt; ./janedoe.tksurfer.lh.tcl
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;tksurfer janedoe rh inflated &lt;span class=&quot;nt&quot;&gt;-gray&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-tcl&lt;/span&gt; ./janedoe.tksurfer.rh.tcl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We make a folder and then run the tcl scripts in &lt;code class=&quot;highlighter-rouge&quot;&gt;tkmedit&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;tksurfer&lt;/code&gt;. The &lt;code class=&quot;highlighter-rouge&quot;&gt;tkmedit&lt;/code&gt; script loops through slices in &lt;code class=&quot;highlighter-rouge&quot;&gt;brain.finalsurfs.mgz&lt;/code&gt; (colored by the automatic segmentation with the surfaces overlayed), taking a screenshot every centimeter. The &lt;code class=&quot;highlighter-rouge&quot;&gt;tksurfer&lt;/code&gt; scripts make screenshots of the lateral &amp;amp; medial views with and without the Destrieux labels.&lt;/p&gt;

&lt;p&gt;At this point we’ve got about 35 pictures to look at and check that segmentation &amp;amp; labeling proceeded normally. In the volume data we’re looking for the colors (the volumetric segmentations) to look accurate and no coloring what is obviously not brain. You also want to ensure the surfaces track well with the image.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;centered&quot; width=&quot;75%&quot; src=&quot;/assets/img/tkmedit-115.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Note that some skull has been left in the what-should-be skull-stripped image and that it’s been labeled as cortex. This is not good but bad results are more enlightening than good ones :)&lt;/p&gt;

&lt;p&gt;On the surface images you’re looking for sharp points in the inflated surfaces–these are bad and are most likely to happen on the medial surface (where it’s not quite as important) or in the temporal pole (which is bad if you’re interested in language). With the labels overlayed, one of these screenshots looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;centered&quot; width=&quot;75%&quot; src=&quot;/assets/img/lh-annot-lateral.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Becuase Freesurfer makes 3D meshes of the white-matter and pial surfaces, we can do fancy things like inflate the brain by pushing out on those meshes. The picture above is the “inflated” view. Each color represents a different labeled region of cortex. Note the spikes in the temporal pole (lowest portion of this view). This is not ideal.&lt;/p&gt;

&lt;p&gt;Freesurfer produces a &lt;strong&gt;lot&lt;/strong&gt; of other data . Given the measure flags I passed above to &lt;code class=&quot;highlighter-rouge&quot;&gt;recon-all&lt;/code&gt;, more than 2650 data points can be extracted from files in the &lt;code class=&quot;highlighter-rouge&quot;&gt;$SUBJECTS_DIR/janedoe/stats/&lt;/code&gt; folder. If you’re interested in that sort of thing, you might take a look at code I wrote &lt;a href=&quot;https://github.com/sburns/recon-stats&quot;&gt;to do just that&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s assume Jane was a great participant and her T1 was very clean. Freesurfer is quite robust and most likely performed good segmentation &amp;amp; labels. On to the diffusion images.&lt;/p&gt;

&lt;h3 id=&quot;diffusion-processing&quot;&gt;Diffusion Processing&lt;/h3&gt;

&lt;p&gt;From our DTI data, we need to produce the following information:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The mask of the non-diffusion-weighted image.&lt;/li&gt;
  &lt;li&gt;A &lt;a href=&quot;http://en.wikipedia.org/wiki/Fractional_anisotropy&quot;&gt;Fractional Anisotropy&lt;/a&gt; (FA) image for registration to the T1.&lt;/li&gt;
  &lt;li&gt;The motion-corrected DTI sequence.&lt;/li&gt;
  &lt;li&gt;PDFs characterizing the underlying diffusion process.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;non-diffusion-weighted-mask&quot;&gt;Non-diffusion-weighted mask&lt;/h4&gt;

&lt;p&gt;For probabalistic tractography, we need to generate a mask within which we constrain tractography. Assuming the first volume of the DTI sequence is the non-diffusion weighted image, we can use &lt;code class=&quot;highlighter-rouge&quot;&gt;bet2&lt;/code&gt; to do this.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;fslroi dti nodif 0 1
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;bet2 nodif nodif_brain &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; .25
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;fslroi&lt;/code&gt; extracts the first time volume from the dti sequence and saves it as &lt;code class=&quot;highlighter-rouge&quot;&gt;nodif.nii.gz&lt;/code&gt;.  Note with FSL commands you do not need to add file extensions. We then use &lt;code class=&quot;highlighter-rouge&quot;&gt;bet2&lt;/code&gt; with a fractional intensity threshold of 0.25. This is generally a robust threshold to remove unwanted tissue from a non-diffusion weighted image. The &lt;code class=&quot;highlighter-rouge&quot;&gt;-m&lt;/code&gt; option creates a binary &lt;code class=&quot;highlighter-rouge&quot;&gt;nodif_brain_mask&lt;/code&gt; image.&lt;/p&gt;

&lt;h4 id=&quot;correcting-for-motion&quot;&gt;Correcting for Motion&lt;/h4&gt;

&lt;p&gt;Because we’re collecting many volumes of diffusion-weighted data from our subject, there’s a very high percentage of some motion between volumes. Also because of how the gradient magnets are used to apply a direction of diffusion and then read out the image, lingering currents in the amplifiers can add artifacts to the data. FSL’s &lt;code class=&quot;highlighter-rouge&quot;&gt;eddy_correct&lt;/code&gt; tool attempts to fix both issues.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;eddy_correct dti dti_ecc 0
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;fdt_rotate_bvecs bvecs rot_bvecs dti_ecc.ecclog
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mv bvecs old_bvecs &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; mv rot_bvecs bvecs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;eddy_correct&lt;/code&gt; takes the raw filename, the output filename and which volume to register all of the gradients to (which is typically the non-diffusion-weighted image). This takes a few seconds per volume, so probably around a minute for full data set.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;fdt_rotate_bvecs&lt;/code&gt; takes the logfile of &lt;code class=&quot;highlighter-rouge&quot;&gt;eddy_correct&lt;/code&gt; and applies the proper rotation to the gradient directions. Because we’ve registered every diffusion volume to the first, the original gradients are not accurate anymore. &lt;code class=&quot;highlighter-rouge&quot;&gt;fdt_rotate_bvecs&lt;/code&gt; fixes this issue. Then we just rename the new gradient vectors to &lt;code class=&quot;highlighter-rouge&quot;&gt;bvecs&lt;/code&gt; without overwriting the old ones.&lt;/p&gt;

&lt;h4 id=&quot;generating-the-fa-image&quot;&gt;Generating the FA image&lt;/h4&gt;

&lt;p&gt;There are much better ways to create an FA image than this method, but as you’ll see below, we’re only using the FA image for registration purposes. I would probably not use this image in a whole-brain FA analysis. For something like that, you might consider using &lt;a href=&quot;http://cmic.cs.ucl.ac.uk/camino/&quot;&gt;Camino&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dtifit &lt;span class=&quot;nt&quot;&gt;-k&lt;/span&gt; dti_ecc &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; ./dtifit &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; nodif_brain_mask &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; bvecs &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; bvals &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We’re interested in &lt;code class=&quot;highlighter-rouge&quot;&gt;dtifit_FA.nii.gz&lt;/code&gt;. &lt;code class=&quot;highlighter-rouge&quot;&gt;dtifit&lt;/code&gt; doesn’t implement the most state-of-the-art model of diffusion, but for our purposes its fast and good enough.&lt;/p&gt;

&lt;p&gt;&lt;img width=&quot;75%&quot; class=&quot;centered&quot; src=&quot;/assets/img/FA_montage.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;These screenshots were taken with &lt;code class=&quot;highlighter-rouge&quot;&gt;fslview_bin&lt;/code&gt;. On the left is the fractional anisotropy (FA) image. In FA images, values varies between 0 &amp;amp; 1 where 0 represents purely isotropic water diffusion. Picture how a golf ball might bounce around inside a basketball–it could go anywhere. Where the FA image is brightest (towards 1), there is one specific direction that water is likely to diffuse (like rolling a golf ball down a paper-towel rod, there isn’t much place else for it to go). FA is typically highest in large fiber bundles such as the corpus callosum (the axonal bundles connecting the two hemispheres). The right image is color-coded by diffusion direction. Green is Anterior-Posterior, Red is Left-Right &amp;amp; Blue is Inferior-Superior (head-foot). The color intensity in this image is modulated by the FA value.&lt;/p&gt;

&lt;p&gt;Its very important to look at these images for quality assurance. In the right image, we want to make sure our gradient table is correct and that we haven’t flipped two dimensions. If this were the case, the image would look the same but colors would be switched. In the pure FA image, we’re looking for smearing and other ugly artifacts which typically denote large amounts of motion.&lt;/p&gt;

&lt;h4 id=&quot;generating-pdfs&quot;&gt;Generating PDFs&lt;/h4&gt;

&lt;p&gt;At this point we have a motion- &amp;amp; artifact-corrected image (&lt;code class=&quot;highlighter-rouge&quot;&gt;dti_ecc.nii.gz&lt;/code&gt;), the corrected gradient table (&lt;code class=&quot;highlighter-rouge&quot;&gt;bvecs&lt;/code&gt;), the gradient values (&lt;code class=&quot;highlighter-rouge&quot;&gt;bvals&lt;/code&gt;), and a mask of the non-diffusion-weighted image (&lt;code class=&quot;highlighter-rouge&quot;&gt;nodif_brain_mask.nii.gz&lt;/code&gt;). If we were smart, we’d use &lt;code class=&quot;highlighter-rouge&quot;&gt;bedpostx&lt;/code&gt; out of the box to generate PDFs of the diffusion direction and get on with tractography. Unfortunately, &lt;code class=&quot;highlighter-rouge&quot;&gt;bedpostx&lt;/code&gt; takes about 20 minutes per slice and typical datasets contain between 40 and 50 slices so this process takes about 15 hours of compute time. Fortunately, it’s an &lt;strong&gt;extremely&lt;/strong&gt; parallelizable task. So the following script exactly mimics FSL 5’s &lt;code class=&quot;highlighter-rouge&quot;&gt;bedpostx&lt;/code&gt; but can run with a linear speedup based on the amount of processors on your machine.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; ./bedpostx.sh

&lt;span class=&quot;nv&quot;&gt;datadir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;./

&lt;span class=&quot;c&quot;&gt;# Estimation parameters&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;nfibres&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2
&lt;span class=&quot;nv&quot;&gt;fudge&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;span class=&quot;nv&quot;&gt;burnin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1000
&lt;span class=&quot;nv&quot;&gt;njumps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1250
&lt;span class=&quot;nv&quot;&gt;sampleevery&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;25


mkdir &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; bedpostx
mkdir &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; bedpostx/diff_slices
mkdir &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; bedpostx/logs
mkdir &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; bedpostx/logs/pid_&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;
mkdir -p bedpostx/xfms

echo &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;bedpostx_preproc begin &lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;date&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;
bedpostx_preproc.sh &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;datadir&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt; 0
echo &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;bedpostx_preproc end &lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;date&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;
echo

nslices=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;FSLDIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/bin/fslval ./dti_ecc dim3&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;
[ -f bedpostx/commands.txt ] &amp;amp;&amp;amp; rm bedpostx/commands.txt

slice=0
while [ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$slice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt; -lt &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$nslices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt; ]
do
    slicezp=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FSLDIR&lt;/span&gt;/bin/zeropad &lt;span class=&quot;nv&quot;&gt;$slice&lt;/span&gt; 4&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;
    if [ -f bedpostx/diff_slices/data_slice_&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$slicezp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;/dyads2.nii.gz ];then
        echo &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;slice &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$slice&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; has already been processed&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;
    else
        echo &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;FSLDIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/bin/bedpostx_single_slice.sh &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$datadir&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$slice&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; --nfibres=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$nfibres&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; --fudge=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$fudge&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; --burnin=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$burnin&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; --njumps=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$njumps&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; --sampleevery=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$sampleevery&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; --model=1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;gt; bedpostx/commands.txt
    fi
    slice=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$slice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;
done

# parallel processing
echo &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;parallel processing begin &lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;date&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;
run_parallel.py bedpostx/commands.txt --ncpu 12
echo &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;parallel processing end &lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;date&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;
echo

# Clean things up
echo &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;bedpostx_postproc begin &lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;date&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;
bedpostx_postproc.sh &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;datadir&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;
echo &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;bedpostx_postproc end &lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;date&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;
echo

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt; run_parallel.py
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# -*- coding: utf-8 -*-&lt;/span&gt;

&lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot; run_parallel.py

Simple script to run a list of shell commands in parallel.

&quot;&quot;&quot;&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;multiprocessing&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mp&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FileType&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'infile'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FileType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'r'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;file with shell commands to execute&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'-n'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'--ncpu'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Number of CPUs to use (default: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%(default)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;s: all CPUs)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ap&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;cpus_to_use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ncpu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ncpu&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ncpu&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cpu_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'__main__'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;subprocess&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;ap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:])&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;ncpu&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cpus_to_use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ncpu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;infile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# Read commands from already open file and close&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;infile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;infile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

        &lt;span class=&quot;c&quot;&gt;# Create a pool and map run_cmd to the shell commands&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;pool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Pool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;processes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ncpu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;pool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ./bedpostx.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This script should finish in about 90 minutes or so. Much better than 15 hours :)&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;bedpostx&lt;/code&gt; unfortunately doesn’t give us pretty pictures to look at :(&lt;/p&gt;

&lt;h3 id=&quot;preparing-for-tractography&quot;&gt;Preparing for Tractography&lt;/h3&gt;

&lt;h4 id=&quot;structural-constraints&quot;&gt;Structural constraints&lt;/h4&gt;
&lt;p&gt;We’re not there yet! But we can start to combine some of the data. We’ll first generate some images from the structural processing, notably a mask of the ventricles &amp;amp; white matter in both hemispheres.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mkdir &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; anat
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mri_convert &lt;span class=&quot;nv&quot;&gt;$SUBJECTS_DIR&lt;/span&gt;/janedoe/mri/rawavg.mgz anat/str.nii.gz
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mri_convert &lt;span class=&quot;nv&quot;&gt;$SUBJECTS_DIR&lt;/span&gt;/janedoe/mri/orig.mgz anat/fs.nii.gz
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mri_binarize &lt;span class=&quot;nt&quot;&gt;--i&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SUBJECTS_DIR&lt;/span&gt;/janedoe/mri/aparc+aseg.mgz &lt;span class=&quot;nt&quot;&gt;--ventricles&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--o&lt;/span&gt; anat/ventricles.nii.gz
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mri_binarize &lt;span class=&quot;nt&quot;&gt;--i&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SUBJECTS_DIR&lt;/span&gt;/janedoe/mri/aparc+aseg.mgz &lt;span class=&quot;nt&quot;&gt;--match&lt;/span&gt; 2 &lt;span class=&quot;nt&quot;&gt;--o&lt;/span&gt; anat/wm.lh.nii.gz
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mri_binarize &lt;span class=&quot;nt&quot;&gt;--i&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SUBJECTS_DIR&lt;/span&gt;/janedoe/mri/aparc+aseg.mgz &lt;span class=&quot;nt&quot;&gt;--match&lt;/span&gt; 41 &lt;span class=&quot;nt&quot;&gt;--o&lt;/span&gt; anat/wm.rh.nii.gz
&lt;span class=&quot;c&quot;&gt;# Put binarized wm filenames into txt file&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt; anat/wm&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; waypoints.txt
&lt;span class=&quot;c&quot;&gt;# also copy over label files &amp;amp; white surfaces&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rsync &lt;span class=&quot;nv&quot;&gt;$SUBJECTS_DIR&lt;/span&gt;/janedoe/label/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.label label/
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rsync &lt;span class=&quot;nv&quot;&gt;$SUBJECTS_DIR&lt;/span&gt;/janedoe/surf/&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;l,r&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;h.white surf/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We’re going to use these binarized files to constrain tractography.&lt;/p&gt;

&lt;h4 id=&quot;registrations&quot;&gt;Registrations&lt;/h4&gt;

&lt;p&gt;We need to be able to map labels in Freesurfer space to DTI space. Aligning a brain in one modality (T1) to another (DTI) is a process called registration. We’re going to perform a number of registrations to produce a transform matrix that places a Freesurfer label into DTI space.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# transform filenames&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ fs2str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;bedpostx/xfms/fs2str.mat
&lt;span class=&quot;nv&quot;&gt;$ str2fs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;bedpostx/xfms/str2fs.mat
&lt;span class=&quot;nv&quot;&gt;$ fa2fs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;bedpostx/xfms/fa2fs.mat
&lt;span class=&quot;nv&quot;&gt;$ fs2fa&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;bedpostx/xfms/fs2fa.mat
&lt;span class=&quot;nv&quot;&gt;$ fa2str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;bedpostx/xfms/fa2str.mat
&lt;span class=&quot;nv&quot;&gt;$ str2fa&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;bedpostx/xfms/str2fa.mat
&lt;span class=&quot;c&quot;&gt;# register structurual to Fs&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;tkregister2 &lt;span class=&quot;nt&quot;&gt;--mov&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$fs&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--targ&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$str&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--regheader&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--reg&lt;/span&gt; /tmp/junk &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--fslregout&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$fs2str&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--noedit&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# invert to create str2fs&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;convert_xfm &lt;span class=&quot;nt&quot;&gt;-omat&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$str2fs&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-inverse&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$fs2str&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Now transforming FA to structural:&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;flirt &lt;span class=&quot;nt&quot;&gt;-in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$fa&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-ref&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$str&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-omat&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$fa2str&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-dof&lt;/span&gt; 6
&lt;span class=&quot;c&quot;&gt;# invert to create str2fa&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;convert_xfm &lt;span class=&quot;nt&quot;&gt;-omat&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$str2fa&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-inverse&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$fa2str&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Concatenate and inverse&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;convert_xfm &lt;span class=&quot;nt&quot;&gt;-omat&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$fa2fs&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-concat&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$str2fs&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$fa2str&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;convert_xfm &lt;span class=&quot;nt&quot;&gt;-omat&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$fs2fa&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-inverse&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$fa2fs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At this point, we have a registration matrix &lt;code class=&quot;highlighter-rouge&quot;&gt;bedpostx/xfms/fs2fa.mat&lt;/code&gt; that we’ll give to &lt;code class=&quot;highlighter-rouge&quot;&gt;probtrackx2&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;generating-seeds&quot;&gt;Generating Seeds&lt;/h4&gt;

&lt;p&gt;Still more to do and we haven’t even started tractography yet! Now we need to convert the label files from Freesurfer into binary volume images that &lt;code class=&quot;highlighter-rouge&quot;&gt;probtrackx2&lt;/code&gt; can read. For this, I’m going to convert them with Freesurfer’s (appropriately labeled) &lt;code class=&quot;highlighter-rouge&quot;&gt;mri_label2vol&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ seed_list&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;seeds.txt
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;hemi &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;lh rh
&lt;span class=&quot;k&quot;&gt;do
    for &lt;/span&gt;lab &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;label_order.txt&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;do
        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;label/&lt;span class=&quot;nv&quot;&gt;$hemi&lt;/span&gt;.&lt;span class=&quot;nv&quot;&gt;$lab&lt;/span&gt;.label
        &lt;span class=&quot;nv&quot;&gt;vol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;/%.label/.gii&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;converting &lt;span class=&quot;nv&quot;&gt;$label&lt;/span&gt; to &lt;span class=&quot;nv&quot;&gt;$vol&lt;/span&gt;
        mri_label2vol &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;--label&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$label&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;--temp&lt;/span&gt; anat/orig.nii.gz &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;--o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$vol&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;--identity&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;--fillthresh&lt;/span&gt; 0.5 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /dev/null
        &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$vol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$seed_list&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;done
done&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;label_order.txt
G_rectus
G_subcallosal
S_suborbital
S_orbital_med-olfact
G_orbital
S_orbital-H_Shaped
G_and_S_transv_frontopol
G_and_S_cingul-Ant
G_and_S_frontomargin
G_front_sup
S_front_sup
S_front_middle
G_front_middle
S_orbital_lateral
S_front_inf
G_front_inf-Triangul
G_front_inf-Orbital
Lat_Fis-ant-Horizont
Lat_Fis-ant-Vertical
S_circular_insula_ant
S_circular_insula_sup
G_insular_short
G_Ins_lg_and_S_cent_ins
S_precentral-inf-part
G_front_inf-Opercular
S_precentral-sup-part
G_precentral
S_central
G_and_S_subcentral
Lat_Fis-post
S_circular_insula_inf
G_temp_sup-Plan_polar
Pole_temporal
G_temp_sup-G_T_transv
S_temporal_transverse
G_temp_sup-Plan_tempo
G_temp_sup-Lateral
S_temporal_sup
G_temporal_middle
S_temporal_inf
G_temporal_inf
S_collat_transv_ant
S_collat_transv_post
G_oc-temp_med-Parahip
S_oc-temp_lat
G_oc-temp_lat-fusifor
G_pariet_inf-Supramar
G_postcentral
S_postcentral
G_and_S_paracentral
G_parietal_sup
S_intrapariet_and_P_trans
S_interm_prim-Jensen
G_pariet_inf-Angular
S_occipital_ant
G_and_S_occipital_inf
G_occipital_middle
S_oc_sup_and_transversal
G_occipital_sup
G_cuneus
S_oc_middle_and_Lunatus
Pole_occipital
S_oc-temp_med_and_Lingual
G_oc-temp_med-Lingual
S_calcarine
S_parieto_occipital
G_precuneus
S_subparietal
G_cingul-Post-dorsal
G_cingul-Post-ventral
S_pericallosal
S_cingul-Marginalis
G_and_S_cingul-Mid-Post
G_and_S_cingul-Mid-Ant
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I empirically determined this ordering of labels &lt;a href=&quot;http://nbviewer.ipython.org/gist/anonymous/9934490&quot;&gt;in this notebook&lt;/a&gt; but I removed &lt;code class=&quot;highlighter-rouge&quot;&gt;BA*&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;cortex&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;entorhinal&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;MT&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;V*&lt;/code&gt; labels since they overlap with the 2009 atlas. &lt;code class=&quot;highlighter-rouge&quot;&gt;seeds.txt&lt;/code&gt; now contains 148 (74 labels * 2 hemispheres) paths to our volumes of interest.&lt;/p&gt;

&lt;p&gt;Just for a sanity check, let’s overlay a few of these volumes on the T1 image in Freesurfer space:&lt;/p&gt;

&lt;p&gt;&lt;img width=&quot;75%&quot; class=&quot;centered&quot; src=&quot;/assets/img/label_overlay.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now we’re ready to being tractography&lt;/strong&gt; (If you’re still with me, I applaud you)&lt;/p&gt;

&lt;h3 id=&quot;tractography&quot;&gt;Tractography&lt;/h3&gt;

&lt;p&gt;At this point, you’re going to need a big computer. Each of these 148 seed regions can run independently, so if you have access to a compute cluster, by all means use it. For each probtracking run, we’re going to do this:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;probtrackx2 &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt; label/lh.G_and_S_cingul-Ant.nii.gz &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; bedpostx/merged &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; bedpostx/nodif_brain_mask &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--usef&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--s2tastext&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--os2t&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--onewaycondition&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; 0.2 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; 2000 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--steplength&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0.5 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-P&lt;/span&gt; 5000 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--fibthresh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0.01 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--distthresh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0.0 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--sampvox&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0.0 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--xfm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;bedpostx/xfms/fs2fa.mat &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--avoid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;anat/ventricles.nii.gz &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--seedref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;anat/fs.nii.gz &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--forcedir&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--opd&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-V&lt;/span&gt; 1 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--omatrix1&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;results/lh.G_and_S_cingul-Ant.nii.gz.probtrackx2/ &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--waypoints&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;waypoints.txt &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--waycond&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'OR'&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--targetmasks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;seeds.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s an exercise to the reader to generate 148 of these scripts. I suggest python :)&lt;/p&gt;

&lt;p&gt;Let’s walk through the options because I’ve wasted many months of compute time generating crap results.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;-x&lt;/code&gt; is the seed. This will differ for each run.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;-s&lt;/code&gt; is the merged samples from &lt;code class=&quot;highlighter-rouge&quot;&gt;bedpostx&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;-m&lt;/code&gt; is the non-diffusion brain mask.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;-l&lt;/code&gt; performs loop checks on paths.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;-usef&lt;/code&gt; uses FA for constrain prob tracking.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--s2tastext&lt;/code&gt; outputs text files for all generated tracts. You &lt;em&gt;must&lt;/em&gt; set this along with &lt;code class=&quot;highlighter-rouge&quot;&gt;-os2t&lt;/code&gt; to generate the proper output files.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--os2t&lt;/code&gt; Outputs seeds to target images. One per voxel in the seed. There can be quite a lot of these files.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--onewaycondition&lt;/code&gt; applies waypoint conditions to each half of the tract separately (see &lt;code class=&quot;highlighter-rouge&quot;&gt;--waypoints&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;-c 0.2&lt;/code&gt; constrains curvature of the generated tracts. This is the default.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;-S 2000&lt;/code&gt; Each tract is created by &lt;em&gt;at the most&lt;/em&gt; 2000 steps.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--steplength=0.5&lt;/code&gt; gives step length in mm. &lt;code class=&quot;highlighter-rouge&quot;&gt;-S&lt;/code&gt; * –steplength` is the maximum length a tract can be.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;-P 5000&lt;/code&gt; the number of sample tracts generated. This number above all else determines the time it takes to run this.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--fibthresh=0.01&lt;/code&gt; thresholds the point at which probtrack will consider orientations of differing directions.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--distthresh=0.0&lt;/code&gt; samples shorter than this length are discarded.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--sampvox=0.0&lt;/code&gt; randomly sample the points with 0.0 mm sphere of the seed voxel. I set this to zero because I trust the incoming seed.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--xfm=bedpostx/xfms/fs2fa.mat&lt;/code&gt; this sets the &lt;strong&gt;linear&lt;/strong&gt; transform from seed space to DTI space.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--meshspace=freesurfer&lt;/code&gt; We’re using Freesurfer meshes.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--avoid=$ventricles&lt;/code&gt; Generated samples to run into the &lt;code class=&quot;highlighter-rouge&quot;&gt;--avoid&lt;/code&gt; image (or iamges) are flat-out rejected. Anatomically speaking, fiber tracts do not pass through the ventricles.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--seedref=anat/brain.nii.gz&lt;/code&gt; this merely gives the reference space for the seeds. Output images are of this size and shape.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--forcedir&lt;/code&gt; use the results directory given, don’t create a new one.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--opd&lt;/code&gt; output the distributions of the samples.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;-V 1&lt;/code&gt; Verbosity level&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--omatrix1&lt;/code&gt; We’re interested in the seed-to-targets matrix.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--dir=results/lh.G_and_S_cingul-Ant.gii.probtrackx2/&lt;/code&gt; directory for results.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--waypoints=waypoints.txt&lt;/code&gt; this file, which for me contains the paths to the white matter binarized images, requires that generated samples pass through these way points. Samples that don’t are rejected. I’m assuming that pathways I care about pass through white matter.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--waycond='OR'&lt;/code&gt; this determines the boolean logic for rejecting (or keeping) pathways given by &lt;code class=&quot;highlighter-rouge&quot;&gt;--waypoints&lt;/code&gt;. In this instance, I only want the stream lines to pass through the left or right white matter, not necessarily both.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;--targetmasks=seeds.txt&lt;/code&gt; This file gives path names to the seeds of interest. As I said before, this is every region from the brain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The time it takes &lt;code class=&quot;highlighter-rouge&quot;&gt;probtrackx2&lt;/code&gt; to finish a region depends on the size of the region. As you can see above in the cortical parcellation picture, not all regions are the same size. Hence some runs don’t take very long (~90 minutes) and others will take a &lt;strong&gt;very long time&lt;/strong&gt;, upwards of 96 hours on modern hardware. Having done this processing on a few subjects, I can say that all told these runs take about 30 days of compute time &lt;strong&gt;per subject&lt;/strong&gt;. Grab a coffee and pillow.&lt;/p&gt;

&lt;h3 id=&quot;analysis&quot;&gt;Analysis&lt;/h3&gt;

&lt;p&gt;When everything is finished, we’d like to visualize the NxN connectivity matrix. We get two important outputs from our &lt;code class=&quot;highlighter-rouge&quot;&gt;probtrackx2&lt;/code&gt; runs. &lt;code class=&quot;highlighter-rouge&quot;&gt;fdt_paths.nii.gz&lt;/code&gt; can be overlayed on the reference file and contains a count at every voxel of how many streamlines passed through that voxel. The other output of interest is &lt;code class=&quot;highlighter-rouge&quot;&gt;matrix_seeds_to_all_targets.nii.gz&lt;/code&gt;. This is a 2D voxel-by-target matrix. By collapsing across all seed voxels and dividing by the total number of streamlines generated during the run, we generate a 1xN array of percentages representing the proportion of streamlines that reached each target. By doing this for all 148 output matrices and stacking the arrays, we generate a 148x148 connectivity matrix.&lt;/p&gt;

&lt;p&gt;Here is my implementation in python:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;matplotlib&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mpl&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mpl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pyplot&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;nibabel&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;collapse_probtrack_results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;waytotal_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matrix_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;waytotal_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;waytotal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nibabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;collapsed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;waytotal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;100.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collapsed&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;matrix_template&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'results/{roi}.nii.gz.probtrackx2/matrix_seeds_to_all_targets.nii.gz'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;processed_seed_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'.nii.gz'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'label/'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'seeds.txt'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;N&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;processed_seed_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zeros&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rois&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;roi&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;processed_seed_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;matrix_file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;roi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;roi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;seed_directory&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;roi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;basename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seed_directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'.nii.gz.probtrackx2'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;waytotal_file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seed_directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'waytotal'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rois&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;roi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# if this particular seed hasn't finished processing, you can still&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# build the matrix by catching OSErrors that pop up from trying&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# to open the non-existent files&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collapse_probtrack_results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;waytotal_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matrix_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;OSError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# figure plotting&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fig&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_subplot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;111&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cax&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matshow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;interpolation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'nearest'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_cmap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'hot'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;caxes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_axes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# set number of ticks&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;caxes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xticks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_order&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;caxes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_yticks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_order&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# label the ticks&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;caxes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xticklabels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_order&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rotation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;caxes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_yticklabels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_order&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rotation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# axes labels&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;caxes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Target ROI'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;caxes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Seed ROI'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Colorbar&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cbar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fig&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;colorbar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cbar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;% &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;of streamlines from seed to target'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rotation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# title text&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;title_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Structural Connectivity with Freesurfer Labels &amp;amp; ProbtrackX2'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;26&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;title_text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/adj.png&quot; width=&quot;75%&quot; class=&quot;centered&quot; /&gt;
&lt;a class=&quot;center&quot; href=&quot;/assets/img/adj.png&quot;&gt;Link to full image&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The diagonal is connectivity from the seed to itself so it makes sense that is very “hot”. Close to off-diagonal we see the most connectivity which also makes sense because I’ve constrained the list to be anatomically “nearby”. I’ve got a few ideas about what to do with this matrices, but I’ll save that for another day.&lt;/p&gt;

</description>
      </item>
    
      <item>
        <title>Using Conda For Quicker Travis Builds</title>
        <link>http://sburns.org/2014/03/28/faster-travis-builds.html</link>
        <pubDate>Fri, 28 Mar 2014 00:00:00 UTC</pubDate>
        <author></author>
        <guid>http://sburns.org/2014/03/28/faster-travis-builds.html</guid>
        <description>&lt;p&gt;&lt;em&gt;Update: This post was spurred by a &lt;a href=&quot;https://twitter.com/scottsburns/status/444216195773120512&quot;&gt;brief exchange on Twitter&lt;/a&gt; with Matt Davis (&lt;a href=&quot;https://twitter.com/jiffyclub&quot;&gt;@jiffyclub&lt;/a&gt;). Apologies for not attributing this originally.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Like I’ve said in the &lt;a href=&quot;/2014/01/28/packaging-best-practices.html&quot;&gt;past&lt;/a&gt;, it’s irresponsible to produce and share un-tested code. &lt;a href=&quot;https://travis-ci.org&quot;&gt;Travis-CI&lt;/a&gt; is a system that takes testing one step farther. They’ve setup an integration with Github such that when commits on any branch are pushed to your repository, Travis will pull the branch to one of their testing servers and execute a series of tests on your behalf. This is fantastic because:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Users don’t have to take your word that this package is tested.&lt;/li&gt;
  &lt;li&gt;Potential contributors don’t need to setup their own testing infrastructure. If they submit a pull-request, Travis will pick it up and test it. Github will display the result of the Travis test on the pull-request page. Both the maintainer (you) and the contributor know this submission passes tests. If it doesn’t, discussions can ensue.&lt;/li&gt;
  &lt;li&gt;Because Travis always runs a test in a new environment, as a package owner you don’t have to worry about false positives when testing locally, i.e. some particular aspect of your local setup biasing test results.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Travis uses a &lt;code class=&quot;highlighter-rouge&quot;&gt;.travis.yml&lt;/code&gt; file in your repository to setup, run &amp;amp; teardown tests. Setup often involves installing one or more dependencies, running usually invokes a test-runner like &lt;a href=&quot;https://nose.readthedocs.org/en/latest/&quot;&gt;nose&lt;/a&gt; or &lt;a href=&quot;http://pytest.org/latest/&quot;&gt;py.test&lt;/a&gt; and teardown may include notification of test results through email or other channels. Travis has &lt;a href=&quot;http://docs.travis-ci.com/user/build-configuration/&quot;&gt;lots of helpful documentation&lt;/a&gt; about writing a good &lt;code class=&quot;highlighter-rouge&quot;&gt;.travis.yml&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Bedrock packages such as &lt;a href=&quot;http://www.numpy.org&quot;&gt;numpy&lt;/a&gt;, &lt;a href=&quot;http://www.scipy.org&quot;&gt;scipy&lt;/a&gt; &amp;amp; &lt;a href=&quot;http://pandas.pydata.org&quot;&gt;pandas&lt;/a&gt; are the building blocks for many scientific and data analysis applications in python. For performance reasons, these packages often include C extensions meaning they either require compilation from source before using or be installed as a pre-built binary. &lt;code class=&quot;highlighter-rouge&quot;&gt;pip&lt;/code&gt;, the go-to python package installer, does not install these packages as binaries. This is an issue if you’re testing on Travis because while they build successfully on the platform, this process can take a long time relative to the time required to test your package.&lt;/p&gt;

&lt;p&gt;Enter &lt;code class=&quot;highlighter-rouge&quot;&gt;conda&lt;/code&gt;, a up-and-coming package manager from the folks at &lt;a href=&quot;http://continuum.io&quot;&gt;Continuum Analytics&lt;/a&gt;. Continuum provides pre-built binaries of many scientific &amp;amp; data analysis packages. &lt;code class=&quot;highlighter-rouge&quot;&gt;conda&lt;/code&gt; will, instead of downloading the source and building as does &lt;code class=&quot;highlighter-rouge&quot;&gt;pip&lt;/code&gt;, download the pre-built binaries from Continuum’s servers and simply move them into place. This makes for faster, more stable &amp;amp; deterministic builds of your go-to libraries.&lt;/p&gt;

&lt;p&gt;How can you use &lt;code class=&quot;highlighter-rouge&quot;&gt;conda&lt;/code&gt; on Travis? Here’s an example &lt;code class=&quot;highlighter-rouge&quot;&gt;.travis.yml&lt;/code&gt; for python:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: python
python:
  - &quot;2.7&quot;
  - &quot;3.3&quot;
install:
  # Install conda
  - sudo pip install conda
  # install deps
  - sudo conda init
  - sudo conda update conda --yes
  - deps='pip numpy pandas requests nose numpydoc sphinx'
  - conda create -p $HOME/py --yes $deps &quot;python=$TRAVIS_PYTHON_VERSION&quot;
  - export PATH=$HOME/py/bin:$PATH
  # install your own package into the environment
  - python setup.py install
script:
- &quot;nosetests -w test/ -v&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;install&lt;/code&gt; key defines a set of steps Travis will take to setup your testing environment. The steps above download, initialize &amp;amp; update &lt;code class=&quot;highlighter-rouge&quot;&gt;conda&lt;/code&gt; and then create a conda environment in &lt;code class=&quot;highlighter-rouge&quot;&gt;$HOME/py&lt;/code&gt; into which dependencies are installed (set in the &lt;code class=&quot;highlighter-rouge&quot;&gt;deps&lt;/code&gt; variable). Finally, &lt;code class=&quot;highlighter-rouge&quot;&gt;python setup.py install&lt;/code&gt; installs your package into the conda environment. After that, the steps defined in &lt;code class=&quot;highlighter-rouge&quot;&gt;script&lt;/code&gt; are executed. Here, we’re simply invoking &lt;code class=&quot;highlighter-rouge&quot;&gt;nosetests&lt;/code&gt; to search for tests and execute them.&lt;/p&gt;

&lt;p&gt;My Travis builds of &lt;a href=&quot;http://pycap.rtfd.org&quot;&gt;PyCap&lt;/a&gt; have gone from between 5-6 minutes to about 90 seconds on the same test battery simply by using &lt;code class=&quot;highlighter-rouge&quot;&gt;conda&lt;/code&gt; to install numpy and pandas.&lt;/p&gt;

&lt;p&gt;Because Travis is a shared resource, developers should try to optimize build time so Travis is testing our code and not wasting time building the same packages over &amp;amp; over again. If your software requires scipy, numpy, pandas or other bedrock packages, I highly recommend taking the time to change your testing process on Travis.&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>Packaging Best Practices</title>
        <link>http://sburns.org/2014/01/28/packaging-best-practices.html</link>
        <pubDate>Tue, 28 Jan 2014 00:00:00 UTC</pubDate>
        <author></author>
        <guid>http://sburns.org/2014/01/28/packaging-best-practices.html</guid>
        <description>&lt;p&gt;You’ve got a brilliant idea you want to implement in software. Congratulations, ideas are energizing. You hope it’ll be good enough that others will want to use it. You might even want others to contribute to your code and make it better. These are all laudable goals. Unfortunately, an idea is nothing without an implementation and an implementation is nothing without proper structure around it. Here are some simple steps you can take to produce better, more professional software.&lt;/p&gt;

&lt;p&gt;I hope this guide is both timeless and language agnostic but I’ll probably sprinkle in specific services &amp;amp; tools that I use to make my life easier.&lt;/p&gt;

&lt;h3 id=&quot;packaging-best-practices&quot;&gt;Packaging Best Practices&lt;/h3&gt;

&lt;p&gt;Starting a new package is always a good time to re-orient yourself with best practices for your particular language &amp;amp; environment. Packaging techniques seem to change every 2-3 years in the python world. Look to popular, well-designed packages as a guide for packaging. In the python world, &lt;a href=&quot;http://docs.python-requests.org/en/latest/&quot;&gt;requests&lt;/a&gt; is your best bet for an easy-to-understand package. I always look at it when starting a new package.&lt;/p&gt;

&lt;h3 id=&quot;version-control&quot;&gt;Version control&lt;/h3&gt;

&lt;p&gt;This should go without saying, but &lt;a href=&quot;http://en.wikipedia.org/wiki/Revision_control&quot;&gt;version control&lt;/a&gt; is an absolute necessity. Consider it an infinite “undo” button. Modern VCS systems like &lt;a href=&quot;http://git-scm.com&quot;&gt;git&lt;/a&gt; and &lt;a href=&quot;http://mercurial.selenic.com&quot;&gt;mercurial&lt;/a&gt; make it dead-simple to create branches off your main codebase for new features, bug-fixes and places for experimentation without affecting “production” code.&lt;/p&gt;

&lt;p&gt;Learn a VCS and use it. Personally I prefer git because of &lt;a href=&quot;https://github.com&quot;&gt;GitHub&lt;/a&gt; and the ability to commit without an internet connection (looking at you Subversion). Remember though that tools are just tools. Don’t get lost in tribal wars.&lt;/p&gt;

&lt;h3 id=&quot;readme-driven-development&quot;&gt;README-driven development&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://tom.preston-werner.com/2010/08/23/readme-driven-development.html&quot;&gt;README Driven Development&lt;/a&gt; says to write your README first. If you’re gung-ho about developing software for others to use, gather your thoughts about what problem(s) you’re solving and how you expect your users to interact with your software.&lt;/p&gt;

&lt;p&gt;Consider your README the initial specification you’re trying to hit. Before there exists any code in your package, you can take the time to truly consider what you’re trying to do. The more code you’ve written, the more difficult it is to about-face on any particular idea, goal, design or implementation.&lt;/p&gt;

&lt;h3 id=&quot;setup-testing-infrastructure&quot;&gt;Setup testing infrastructure&lt;/h3&gt;

&lt;p&gt;Nobody gets into software development because &lt;a href=&quot;http://en.wikipedia.org/wiki/Unit_testing&quot;&gt;unit-&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/Functional_testing&quot;&gt;functional-testing&lt;/a&gt; is fun. However, asking people to use un-tested software is careless, unprofessional and downright malevolent. Work hard to reduce the impediments to testing your code. Consider dumping your test command(s) into a &lt;a href=&quot;http://en.wikipedia.org/wiki/Make_(software)&quot;&gt;Makefile&lt;/a&gt;. If your testing infrastructure requires separate packages, make it very easy to get those packages.&lt;/p&gt;

&lt;p&gt;As an aside, &lt;a href=&quot;http://pytest.org/latest/&quot;&gt;py.test&lt;/a&gt; let’s you generate a script that runs your tests. The script contains a copy of the py.test package and therefore contributors don’t need to download &amp;amp; install py.test. Brilliant if you ask me.&lt;/p&gt;

&lt;h4 id=&quot;continuous-integration&quot;&gt;Continuous Integration&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Continuous_integration&quot;&gt;Continuous Integration (CI)&lt;/a&gt; is the practice of merging development branches often to reduce integration hell. Unless we’ve tested the development branches, they shouldn’t be considered correct or valid. Therefore try to setup some sort of continuous testing service. If your package is on GitHub, take the 5 minutes to write a &lt;code class=&quot;highlighter-rouge&quot;&gt;.travis.yml&lt;/code&gt; file and setup the hooks to get pushed branches tested on &lt;a href=&quot;https://travis-ci.org&quot;&gt;TravisCI&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;documentation-is-king&quot;&gt;Documentation is king&lt;/h3&gt;

&lt;p&gt;It’s a lie to think you’re working alone on a software project. Six months from now you will have forgotten why you made a particular decision in some small function and you will be working with (hopefully not against :) a previous version of yourself at that point. Wouldn’t it be nice to find the piece of documentation detailing that decision?&lt;/p&gt;

&lt;p&gt;If you’re working with others, documentation is an absolute necessity. Not only does it keep developers on the same page but also gives users some confidence that you care about your work enough to write about it. Writing prose about your software also invariably helps you form better ideas about why you’re writing this software, who should use this software &amp;amp; what your users will want to get out of this package.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://sphinx-doc.org&quot;&gt;Sphinx&lt;/a&gt; is the go-to tool for writing documentation for python packages. Couple it with &lt;a href=&quot;https://readthedocs.org&quot;&gt;ReadTheDocs&lt;/a&gt;, a service that automatically builds and hosts your documentation for open-source projects.&lt;/p&gt;

&lt;p&gt;I have not found a better site devoted to documentation than &lt;a href=&quot;http://docs.writethedocs.org/en/latest/&quot;&gt;WriteTheDocs&lt;/a&gt;. Read it and understand why documentation is so important to your software.&lt;/p&gt;

&lt;h3 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h3&gt;

&lt;p&gt;I hope these tips will help someone write more professional code. I just started working on something new and thinking about developing a more complete, user-friendly package spurred this post. I should have more to say about my new package soon.&lt;/p&gt;

</description>
      </item>
    
      <item>
        <title>Tools, Libraries & Applications</title>
        <link>http://sburns.org/2014/01/26/apps-libs-tools.html</link>
        <pubDate>Sun, 26 Jan 2014 00:00:00 UTC</pubDate>
        <author></author>
        <guid>http://sburns.org/2014/01/26/apps-libs-tools.html</guid>
        <description>&lt;p&gt;By training, I’m not a software engineer. I’m willing to bet the majority of those who develop software to produce science weren’t trained as such either, which is why &lt;a href=&quot;http://software-carpentry.org&quot;&gt;Software Carpentry&lt;/a&gt; is so important.&lt;/p&gt;

&lt;p&gt;At its core, we produce science by applying one or methods against one or more datasets. The exact methods and datasets depend on the field and its current best practices. One can develop their own methods or use freely available tools. Vice versa, one might collect their own data or use publicly-available datasets. Either way, science needs a method and data to apply it against. We then can make inferences about the world.&lt;/p&gt;

&lt;p&gt;Typically, if you’re developing methods for others to use, you’ll test your tool(s) against a public dataset so your results can be compared with other, similar methods. If you’re collecting your own data (perhaps from a unique population), you’ll probably want to use a public toolchain for analysis. Any variance in the results should be wholly attributable to the collected data and not the toolset.&lt;/p&gt;

&lt;p&gt;There is a relationship between our tools and data and the better we understand this, the more reliable and reproducible our analyses become. I think this relationship takes the form of a &lt;a href=&quot;http://en.wikipedia.org/wiki/Solution_stack&quot;&gt;stack&lt;/a&gt;. At the bottom of the stack, we have low-level tools that do the nitty gritty work. We may abstract these tools into libraries so they can more easily be used both alone and together. Finally, we produce applications built upon common, shared libraries that ask specific questions using specific data.&lt;/p&gt;

&lt;p&gt;The following should be obvious to any professional developer. I’ll use examples from neuroimaging but this should generalize to all fields of science.&lt;/p&gt;

&lt;h3 id=&quot;tools&quot;&gt;Tools&lt;/h3&gt;

&lt;p&gt;Lots of fields have robust &amp;amp; mature toolsets for data analysis. In neuroimaging, some of these packages include &lt;a href=&quot;http://surfer.nmr.mgh.harvard.edu&quot;&gt;Freesurfer&lt;/a&gt;, &lt;a href=&quot;http://fsl.fmrib.ox.ac.uk/fsl/fslwiki/&quot;&gt;FSL&lt;/a&gt; and &lt;a href=&quot;http://www.fil.ion.ucl.ac.uk/spm/&quot;&gt;SPM&lt;/a&gt;. Lots of energy and work have been poured into the tools these packages expose and they’ve been tested against a wide variety of datasets. No reviewer will scoff at the usage of any of these tools.&lt;/p&gt;

&lt;p&gt;However, no one would call these packages cutting-edge. Researchers across the world are continually developing novel algorithms for image processing and statistical analyses and as these procedures mature, they too become dependable tools for the rest of the community to use.&lt;/p&gt;

&lt;p&gt;However, none of these tools will produce results for a scientific paper in and of themselves. The minimum work to be done is to apply these tools against your dataset. This is always done by developing by an “application” that uses these tools.&lt;/p&gt;

&lt;h3 id=&quot;applications&quot;&gt;Applications&lt;/h3&gt;

&lt;p&gt;Applications are highly dependent on the researchers data, hypotheses and available computing infrastructure. They can be as simple as a single script that passes acquired data to tools. They can also become quite complex, integrating many sources of data to many paths for analyses. Either way, it’s very hard to share applications across research groups because their requirements are so specific and tuned.&lt;/p&gt;

&lt;p&gt;This isn’t necessarily bad though. There is much knowledge to be gained in developing these applications and students should seek this exposure as much as possible. Building an application exposes one to how tools should be used as well as confirming the research questions meant to be addressed are being answered.&lt;/p&gt;

&lt;h3 id=&quot;libraries&quot;&gt;Libraries&lt;/h3&gt;

&lt;p&gt;Especially within a research group, applications will often lean on the same or a similar set of tools. Libraries can play a useful layer between tools and applications. Libraries should expose tools in a common form such that disparate applications can independently use these tools to address specific research questions. These libraries serve to gather our accumulated knowledge of best practices for using a particular tool. This is a form of &lt;a href=&quot;http://en.wikipedia.org/wiki/Don't_repeat_yourself&quot;&gt;Don’t Repeat Yourself (DRY)&lt;/a&gt;, a powerful methodology for building software.&lt;/p&gt;

&lt;p&gt;These libraries have two requirements. First, they should present a unified interface for building commands to execute tools. Each tool requires different data in different forms so these libraries should try and minimize the differences across tools and simplify the use of said tools.&lt;/p&gt;

&lt;p&gt;More importantly, these libraries should make no decisions about how incoming data should be organized or how the generated commands are ultimately executed. These decisions are the discretion of the application layer. Not only does this make libraries more useful to separate research groups but also infintely more testable because they don’t require any particular infrastructure when &lt;a href=&quot;http://en.wikipedia.org/wiki/Unit_testing&quot;&gt;unit testing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As we develop better know-how about using particular tools, we should pour this knowledge into libraries, not applications. Walling off our improved logic into a single application means no other can reap the benefits. Instead, if we update our libraries with improved knowledge and maintain &lt;a href=&quot;http://en.wikipedia.org/wiki/Backwards_compatibility&quot;&gt;backwards compatibility&lt;/a&gt;, all of the applications built upon the library can share the improvements.&lt;/p&gt;

&lt;h3 id=&quot;abstraction&quot;&gt;Abstraction&lt;/h3&gt;

&lt;p&gt;Implicit in the above discussion is the idea of &lt;a href=&quot;http://en.wikipedia.org/wiki/Abstraction_(computer_science)&quot;&gt;abstraction&lt;/a&gt;. Tools abstract their advanced image processing algorithms. Libraries abstract the advanced knowledge of how best to use tools. Applications abstract the all of the above so we can quickly apply methods against our particular dataset and ultimately answer questions about the world.&lt;/p&gt;

&lt;p&gt;No layer is more important than the other. As research software engineers, we should be interested in all layers and keep in mind how changing any particular layer will affect the others. Only when we understand the relationship between our tools, libraries and applications can we begin to engineer better science.&lt;/p&gt;

</description>
      </item>
    
      <item>
        <title>TBSS & IPython.parallel</title>
        <link>http://sburns.org/2013/12/31/ipython_tbss.html</link>
        <pubDate>Tue, 31 Dec 2013 00:00:00 UTC</pubDate>
        <author></author>
        <guid>http://sburns.org/2013/12/31/ipython_tbss.html</guid>
        <description>&lt;h3 id=&quot;a-brief-primer-on-diffusion-tensor-imaging&quot;&gt;A brief primer on Diffusion Tensor Imaging&lt;/h3&gt;

&lt;p&gt;We collect a wide variety of MR data from our children. Along with a high-resolution T1 and functional MR, we also collect a high-angular resolution diffusion image (HARDI), which is a kind of diffusion tensor image (DTI) sequence.This type of MR sequence measures the relative motion of water at every voxel along a variety of gradients (directions) through the brain. The line of thinking goes that water molecules, during their random walk, are more likely to move parallel to axons than cross the myelin sheath. Therefore diffusion imaging is a way to get at structural connectivity because it (hopefully) reveals the white-matter pathways through the brain.&lt;/p&gt;

&lt;p&gt;Much like functional MR, the math behind DTI is not complex. Simply put, we use the many collected images and known gradient direction for each image to solve for the tensor at every voxel. This tensor encapsulates both the direction water will most likely flow in that voxel as well as to the degree it will flow. For each direction (X, Y &amp;amp; Z), the tensor contains information about the relative component of the direction. The average of the X, Y and Z components is called Fractional Anisotropy (FA) and it varies between 0 and 1. For voxels that contain water moving in a very definite direction, FA is high and you might visualize it as a rod pointing in some particular direction. For areas of the brain in which water moves more equally in all three directions, FA is low. This typically occurs in gray matter where axons are much less organized than in white matter.&lt;/p&gt;

&lt;h3 id=&quot;group-modeling&quot;&gt;Group modeling&lt;/h3&gt;

&lt;p&gt;We typically will examine FA maps and look for regions that covary with some behavioral measure. We collect all MR data in what is called subject or native space. In subject space, there is no relation between the actual brain region at any particular voxel in one subject and that same voxel in another subject. Because we collect data from many subjects for statistical power, we employ a method call registration to align every subject’s native space FA image to a template. This template is often in a space that has been labeled with specific anatomical locations. Therefore, once we have all subjects in a template space and find regions that correlate with a behavioral measure, we can look up the anatomical location of that region and make a brilliant scientific conclusion (hopefully).&lt;/p&gt;

&lt;h3 id=&quot;problems&quot;&gt;Problems&lt;/h3&gt;

&lt;p&gt;FA maps are difficult to register to the template because white matter pathways vary widely between subjects and especially so if the subjects will as a whole have different white matter structure from the template. Our child data is very difficult to register to any particular template space.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://fsl.fmrib.ox.ac.uk/fsl/fslwiki/&quot;&gt;FSL&lt;/a&gt;’s &lt;a href=&quot;http://fsl.fmrib.ox.ac.uk/fsl/fslwiki/TBSS&quot;&gt;Tract-Based Spatial Statistics&lt;/a&gt; (TBSS) tool provides what some believe to be the best way to register many FA maps together. In a nutshell, it registers every subject to each other, discovers the most “prototypical” subject and aligns that subject to the template. Stacking the inter-subject registration and the template registrations, each image is brought into template space.&lt;/p&gt;

&lt;p&gt;So, if we have 100 subjects, that’s 100&lt;sup&gt;2&lt;/sup&gt; or 10000 inter-subject registrations to perform. Each registration takes 3-5 minutes, so we’re looking at ~20 days of compute time to do this. Fortunately, this problem is extremely parallelizable because no single registration depends on another. FSL provides a way to send this to a compute cluster. However, typical (especially shared) clusters perform better with long running tasks ( &amp;gt; 1 hr wall time) due to the overhead required in submitting and maintaining running processes on each compute node. Submitting 10000 5-minute jobs would swamp the scheduler and generate some very nasty emails from your cluster system administrator whom you shouldn’t want to upset. We need some way to perform many jobs in parallel with less overhead than a full cluster.&lt;/p&gt;

&lt;h3 id=&quot;solution&quot;&gt;Solution&lt;/h3&gt;

&lt;p&gt;Enter &lt;a href=&quot;http://ipython.org/ipython-doc/stable/parallel/index.html&quot;&gt;IPython.parallel&lt;/a&gt;. IPython provides the architecture and machinery to start engines (processes that will accept work) on separate computers and then submit work from one or more other processes. This is better than python’s &lt;a href=&quot;http://docs.python.org/2/library/multiprocessing.html&quot;&gt;multiprocessing&lt;/a&gt; library that parallelizes only across a single machine. If you only have a single machine at your disposal, I would absolutely use &lt;code class=&quot;highlighter-rouge&quot;&gt;multiprocessing&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First, we need to preprocess our data. Assuming you’re in a directory with all of your FA images:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;tbss_1_preproc &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.nii&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This takes a few seconds per image. Next, we’ll run TBSS’s registration step. The &lt;code class=&quot;highlighter-rouge&quot;&gt;-n&lt;/code&gt; option tells TBSS to run the inter-subject registration:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;tbss_2_reg &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you let this run as is, you’ll need to come back in 20 days. What &lt;code class=&quot;highlighter-rouge&quot;&gt;tbss_2_reg -n&lt;/code&gt; first does is build a list of registrations to perform. It stores this in a text file at &lt;code class=&quot;highlighter-rouge&quot;&gt;FA/.commands&lt;/code&gt;. If you keep running &lt;code class=&quot;highlighter-rouge&quot;&gt;tbss_2_reg&lt;/code&gt;, it will simply begin executing these commands.&lt;/p&gt;

&lt;p&gt;Instead, what I do is kill the &lt;code class=&quot;highlighter-rouge&quot;&gt;tbss_2_reg&lt;/code&gt; command and jump into python. First, read the list of registration commands and define a function we’ll use to execute a single command.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'FA/.commands'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot; execute the command-line call given in `command`

    Note: imports should go in the function as imported
    modules are not global in the IPython cluster&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;subprocess&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;shlex&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;At this point, we need to start up our “cluster”. You should make a new parallel IPython profile for this. I won’t dive into the details of configuring an IPython cluster &lt;a href=&quot;http://ipython.org/ipython-doc/stable/parallel/parallel_process.html&quot;&gt;as the docs are quite good&lt;/a&gt;. Back in a shell, let’s start our cluster:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;screen &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; cluster
...screen session...
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ipcluster &lt;span class=&quot;nt&quot;&gt;--profile-dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/path/to/your/parallel/profile_dir
...output from ipcluster...
...Ctrl-A d to detach your terminal...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I’m a big fan of &lt;a href=&quot;https://www.gnu.org/software/screen/&quot;&gt;screen&lt;/a&gt; for long running processes. &lt;code class=&quot;highlighter-rouge&quot;&gt;ipcluster&lt;/code&gt; is the easy way to start an IPython cluster but it needs to run for as long as you want to do work on that cluster. Simply backgrounding the command (&lt;code class=&quot;highlighter-rouge&quot;&gt;ipcluster ... &amp;amp;&lt;/code&gt;) isn’t enough as terminating a shell session with running jobs will kill the jobs (and your cluster). This method is also pretty explicit in that when you want to stop your cluster, just re-attach and kill the process. If you &lt;code class=&quot;highlighter-rouge&quot;&gt;nohup ipcluster ... &amp;amp;&lt;/code&gt;, you’ll have to hunt around in &lt;code class=&quot;highlighter-rouge&quot;&gt;top&lt;/code&gt; to find the right IPython process to kill.&lt;/p&gt;

&lt;p&gt;With the cluster up and running, back into python:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IPython.parallel&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Client&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;profile_dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'/path/to/your/parallel/profile_dir'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;lview&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load_balanced_view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;len(c)&lt;/code&gt; will be how many engines you have running in this cluster. The &lt;a href=&quot;http://ipython.org/ipython-doc/rel-1.1.0/parallel/parallel_task.html#the-ipython-task-interface&quot;&gt;load balanced view&lt;/a&gt; is the primary method you should use to submit jobs to your cluster.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lview&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map_async&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Much like python’s built-in &lt;code class=&quot;highlighter-rouge&quot;&gt;map&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;lview.map_async&lt;/code&gt; takes a function and an iterable of arguments to pass to that function. Behind the scenes, it does the hard work of submitting jobs to the IPython cluster and grabbing results. Because we’re using the &lt;code class=&quot;highlighter-rouge&quot;&gt;.map_async&lt;/code&gt; function, this will return very quickly. Rest assured, the engines are working very hard now.&lt;/p&gt;

&lt;h3 id=&quot;caveats--conclusions&quot;&gt;Caveats &amp;amp; Conclusions&lt;/h3&gt;

&lt;p&gt;This isn’t the cleanest nor easiest-to-setup method to parallelize TBSS. However, I’ve found IPython’s parallel machinery to be bullet-proof and provide the right level of control when I need to run lots of little jobs. This method is definitely overkill if you have a single machine and like I said above, definitely use &lt;code class=&quot;highlighter-rouge&quot;&gt;multiprocessing&lt;/code&gt; (or better, &lt;a href=&quot;https://github.com/joblib/joblib&quot;&gt;joblib&lt;/a&gt;, a great wrapper around multiprocessing).&lt;/p&gt;

&lt;p&gt;I think this is a great example of just how much IPython can help in your work. If the &lt;a href=&quot;http://ipython.org/ipython-doc/stable/interactive/notebook.html&quot;&gt;notebook&lt;/a&gt; feature sold you on IPython, the parallel tools are just icing on the cake.&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>Video of KC talk is up</title>
        <link>http://sburns.org/2013/07/22/kc-video-talk.html</link>
        <pubDate>Mon, 22 Jul 2013 00:00:00 UTC</pubDate>
        <author></author>
        <guid>http://sburns.org/2013/07/22/kc-video-talk.html</guid>
        <description>&lt;p&gt;I just finished my talk about advanced REDCap usage at the Kennedy Center. Many thanks to Jenny Gilbert for organizing it.&lt;/p&gt;

&lt;p&gt;The fine folks at the Kennedy Center have already &lt;a href=&quot;http://kc.vanderbilt.edu/site/newsandevents/podcastandvideo/page.aspx?id=4036&quot;&gt;posted the video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The PDF version of my final slides is &lt;a href=&quot;/assets/pdf/20130722-kc-redcap-final.pdf&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I think it went over well and I received some nice feedback afterwards. I worked hard to talk less about the exact mechanics of using the API and more about what types of problems we can better solve with the API and Data Entry Triggers.&lt;/p&gt;

&lt;script class=&quot;speakerdeck-embed&quot; data-id=&quot;7ae62d50d82c01304c976e65229c9f4b&quot; data-ratio=&quot;1.33333333333333&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt; &lt;/script&gt;

</description>
      </item>
    
      <item>
        <title>Intro to the REDCap API</title>
        <link>http://sburns.org/2013/07/22/intro-to-redcap-api.html</link>
        <pubDate>Mon, 22 Jul 2013 00:00:00 UTC</pubDate>
        <author></author>
        <guid>http://sburns.org/2013/07/22/intro-to-redcap-api.html</guid>
        <description>&lt;p&gt;As far as I can tell, there isn’t a tutorial on the internet about how to use
the REDCap API. So here goes…&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://project-redcap.org&quot;&gt;REDCap&lt;/a&gt; is an advanced web-based application for
securely storing and retrieving tabular data. In simple terms, it can be thought
of a web-based spreadsheet, though it is much more than that. It provides an
&lt;strong&gt;Application Programming Interface&lt;/strong&gt; which means external software can
programmatically download and upload data into REDCap Projects. This tutorial
assumes working knowledge of REDCap. When all else fails, please consult your
site’s API help page, which is at &lt;a href=&quot;https://redcap.vanderbilt.edu/api/help&quot;&gt;here&lt;/a&gt; for
Vanderbilt.&lt;/p&gt;

&lt;p&gt;Becuase the API is based on simple HTTP requests, any programming langauge with
a HTTP library can use the REDCap API. I’m going to demonstrate simple API usage
in python using the wonderful &lt;a href=&quot;http://python-requests.org&quot;&gt;requests&lt;/a&gt; library.&lt;/p&gt;

&lt;p&gt;To use the REDCap API, you must know the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The API URL for your site’s REDCap installation. For Vanderbilt, this url is
&lt;code class=&quot;highlighter-rouge&quot;&gt;https://redcap.vanderbilt.edu/api/&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The API token for your Project. A token is generated by the REDCap
administrators and connects your user account to a particular REDCap Project.
Therefore, if you have API access to many Projects, you will have many tokens to
manage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;basic-usage&quot;&gt;Basic Usage&lt;/h3&gt;

&lt;p&gt;Every call to the REDCap API is a HTTP POST request with specific parameters in
the payload. The &lt;code class=&quot;highlighter-rouge&quot;&gt;token&lt;/code&gt; parameter is always required as this tells the API from
which Project you’re requesting a response. Next, the &lt;code class=&quot;highlighter-rouge&quot;&gt;content&lt;/code&gt; parameter is
used to declare the type of request you’re making. Finally, you may want to
include the &lt;code class=&quot;highlighter-rouge&quot;&gt;format&lt;/code&gt; field as well as this tells the API in what format you want
the response. It defaults to returning a CSV string, but I generally prefer
getting &lt;a href=&quot;http://www.json.org&quot;&gt;json-formatted&lt;/a&gt; responses as that format can be
easily converted to actual in-memory objects like lists, dictionaries, strings,
etc.&lt;/p&gt;

&lt;p&gt;So let’s begin by making the most simple request, exporting the Project’s
Metadata (AKA Data Dictionary).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;requests&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Two constants we'll use throughout&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TOKEN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'8E66DB6844D58E990075AFB51658A002'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;URL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'https://redcap.vanderbilt.edu/api/'&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'token'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TOKEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'format'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'json'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'content'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'metadata'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status_code&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;A few things to talk about here:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;At least at Vanderbilt, don’t forgot the trailing slash at the end of the
API URL string. Your site may differ but if you mess up the URL, nothing will
work and you’ll probably get 501 “Method Not Implemented” responses.&lt;/li&gt;
  &lt;li&gt;Under no circumstance should you ever publicize your Project token. This is
like publishing the password you use to login to REDCap, which you would never
do. In this instance however, this token is from a dummy project I use to test
things with. There’s no real data and definitely not any PHI in it, so I’m not
super worried.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But just to be clear:&lt;/p&gt;

&lt;h3 id=&quot;under-no-circumstances-should-you-publicize-your-project-tokens&quot;&gt;Under no circumstances should you publicize your project token(s)!&lt;/h3&gt;

&lt;p&gt;You’ve been warned. (If you do publicize them for whatever reason, don’t fret.
Just delete those tokens through the web app ASAP and request new tokens).&lt;/p&gt;

&lt;p&gt;With that out of the way, the API accepted our request and returned data with a
‘200’ status, which means “everything is peachy” in HTTP.&lt;/p&gt;

&lt;p&gt;Now let’s examine our metadata a bit. The &lt;code class=&quot;highlighter-rouge&quot;&gt;.json()&lt;/code&gt; method I’m going to use just
decodes the response (every language’s JSON library will work a bit differently,
though).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;This project has &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;d fields&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;field_name (type) ---&amp;gt; field_label&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;---------------------------&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;s (&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;s) ---&amp;gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;s&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'field_name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'field_type'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'field_label'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Every field has these keys: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;s'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;', '&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;This project has 11 fields

field_name (type) ---&amp;gt; field_label
---------------------------
study_id (text) ---&amp;gt; Study ID
first_name (text) ---&amp;gt; First Name
last_name (text) ---&amp;gt; Last Name
dob (text) ---&amp;gt; Date of Birth
sex (dropdown) ---&amp;gt; Gender
address (notes) ---&amp;gt; Street, City, State, ZIP
phone_number (text) ---&amp;gt; Phone number
file (file) ---&amp;gt; File
foo_score (text) ---&amp;gt; Test score for Foo test
bar_score (text) ---&amp;gt; Test score for Bar test
image_path (text) ---&amp;gt; image_path

Every field has these keys: branching_logic, custom_alignment, field_label, field_name, field_note, field_type, form_name, identifier, matrix_group_name, question_number, required_field, section_header, select_choices_or_calculations, text_validation_max, text_validation_min, text_validation_type_or_show_slider_number
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The returned json decodes to a list of &lt;code class=&quot;highlighter-rouge&quot;&gt;dict&lt;/code&gt; objects (python’s name for hash
tables). We see that there are 11 fields in this project, we print out a mapping
of the &lt;code class=&quot;highlighter-rouge&quot;&gt;field_name&lt;/code&gt; (the “machine” name for a field) along with it’s type and
the &lt;code class=&quot;highlighter-rouge&quot;&gt;field_label&lt;/code&gt; (the human-readable description). Finally, I just print out
all of the keys from the first field so we can look at all of the data that
comes with each field.&lt;/p&gt;

&lt;p&gt;For all intents and purposes, this data structure is what we get when we
manually download the Data Dictionary from our project, just in a slightly more
machine-readable format.&lt;/p&gt;

&lt;h3 id=&quot;data-export&quot;&gt;Data Export&lt;/h3&gt;

&lt;p&gt;Here’s the fun part. Just tweak the request payload a little and we’ll download
all of the data from our project:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'content'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'record'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'type'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'flat'&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# we want each row to contain the entire record&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Voilà, we’ve just downloaded all of the data from our project. Let’s
examine it.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;This project has &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;d records&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Each record has the following keys: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;s.&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;', '&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;But our metadata structure has the following fields: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;s!&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;', '&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'field_name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;This project has 3 records
Each record has the following keys: phone_number, first_name, last_name, image_path, dob, demographics_complete, foo_score, sex, study_id, file, address, imaging_complete, testing_complete, bar_score.

But our metadata structure has the following fields: study_id, first_name, last_name, dob, sex, address, phone_number, file, foo_score, bar_score, image_path!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You’d be wrong to assume the fields we get from exporting the data matches the
&lt;code class=&quot;highlighter-rouge&quot;&gt;field_name&lt;/code&gt;s from the metadata structure. This is because the REDCap API also
returns the status of all of the forms for a particular record. These fields are
always called &lt;code class=&quot;highlighter-rouge&quot;&gt;[form name]_complete&lt;/code&gt; where &lt;code class=&quot;highlighter-rouge&quot;&gt;[form name]&lt;/code&gt; is the lowercased &amp;amp;
underscore-replaced version of the forms you see in the web-application. (You
would be correct to assume the fields from an export are a superset of the
fields from the metadata structure)&lt;/p&gt;

&lt;p&gt;We can examine a particular record like so:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;s: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;s&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;phone_number: (615) 555-1234
first_name: Billy Bob
last_name: blah blah
image_path: /path/to/image
dob: 2000-01-01
demographics_complete: 2
foo_score: 100
sex: 1
study_id: 1
file: [document]
address: 123 Main Street, Anytown USA 23456
imaging_complete: 2
testing_complete: 2
bar_score: 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Pretty neat. Within the &lt;code class=&quot;highlighter-rouge&quot;&gt;payload&lt;/code&gt; that you send to the API, you can specify
parameters that will limit the response to just include specific records,
fields, forms, events (if your Project is longitudinal) and whether to get the
raw or human-label in mutliple-choice fields. Experimenting with these calls is
left to the reader.&lt;/p&gt;

&lt;h3 id=&quot;importing-new-data&quot;&gt;Importing new data&lt;/h3&gt;

&lt;p&gt;Even fancier than exporting current data from the Project is updating records
through the API. This payload looks a little different, though. We’ve got to
encode the data that we want to import and attach it to the payload.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;json&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# the function we'll need to make a json-string of our new data&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;updated_record&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Update a particular field&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;updated_record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'foo_score'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'100'&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#we have to pass a list of records to the redcap API, so we're going to dump our new record within a list&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# and we need to specify how to format the json string&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;to_import_json&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;updated_record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;separators&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;','&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;':'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'data'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_import_json&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'count'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Real quickly:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We updated a field from the first record.&lt;/li&gt;
  &lt;li&gt;We made a json-formatted string of this data structure (after packing it
into a list because that’s what the API wants).&lt;/li&gt;
  &lt;li&gt;We attached this data to the &lt;code class=&quot;highlighter-rouge&quot;&gt;data&lt;/code&gt; field of the payload and made the
request to the API.&lt;/li&gt;
  &lt;li&gt;By default when importing data, the API will respond with a dict with the
key &lt;code class=&quot;highlighter-rouge&quot;&gt;count&lt;/code&gt;. This number is how many records you imported. You can see here that
we import one record.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You might be wondering to yourself, how did the API know which record to update?
That information is specified in the &lt;code class=&quot;highlighter-rouge&quot;&gt;study_id&lt;/code&gt; field because &lt;code class=&quot;highlighter-rouge&quot;&gt;study_id&lt;/code&gt; is the
primary key of the Project, which is by definition the first field in the
metadata (take this opportunity to look back and see that &lt;code class=&quot;highlighter-rouge&quot;&gt;study_id&lt;/code&gt; was in fact
the first field).&lt;/p&gt;

&lt;p&gt;Note, we formatted the incoming data as json because that was the format we
specified in the &lt;code class=&quot;highlighter-rouge&quot;&gt;format&lt;/code&gt; parameter of the payload. You could just as easily
import data formatted as CSV or XML if you change that parameter.&lt;/p&gt;

&lt;p&gt;Exporting and Importing data are the two most important methods of the API. You
can also download, upload and delete files stored in &lt;code class=&quot;highlighter-rouge&quot;&gt;file&lt;/code&gt; fields per record
but doing this is different for every HTTP library so I’ll let you figure it out
for your programming language :)&lt;/p&gt;

&lt;p&gt;That brings us to the end of how to use the REDCap API generally. I’ve
implemented everything above in python, but you’re free to use whatever language
you like as long as it has an HTTP library.&lt;/p&gt;

&lt;p&gt;That being said, python is fantastic language with great libraries for high-
level data manipulation like &lt;a href=&quot;http://pandas.pydata.org&quot;&gt;pandas&lt;/a&gt;, low-level data
structures like &lt;a href=&quot;http://www.numpy.org&quot;&gt;NumPy&lt;/a&gt;, scientific libraries like
&lt;a href=&quot;http://www.scipy.org&quot;&gt;SciPy&lt;/a&gt;. Python is also very popular in web development
communities so there are web frameworks like
&lt;a href=&quot;https://www.djangoproject.com&quot;&gt;Django&lt;/a&gt; and &lt;a href=&quot;http://flask.pocoo.org&quot;&gt;Flask&lt;/a&gt; in
case you want to build websites or applications. If you need to do some advanced
task, there probably exists a python package to help you on your way. It’s a
great platform to build all sorts of tools.&lt;/p&gt;

&lt;h2 id=&quot;using-the-redcap-api-in-python-applications&quot;&gt;Using the REDCap API in Python Applications&lt;/h2&gt;

&lt;p&gt;To make it easier to use the REDCap API from within python scripts and
applications, I wrote &lt;a href=&quot;http://sburns.github.io/PyCap&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;PyCap&lt;/code&gt;&lt;/a&gt;. I’ll assume a
Mac OS X or Linux environment, though all of this should work on Windows. It
assumes working knowledge of the shell and the python language.&lt;/p&gt;

&lt;p&gt;First, we must install the package. In a shell:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;$ pip install PyCap&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you don’t have &lt;code class=&quot;highlighter-rouge&quot;&gt;pip&lt;/code&gt; installed, this will work (you really should though,
&lt;code class=&quot;highlighter-rouge&quot;&gt;easy_install&lt;/code&gt; is considered deprecated by much of the python community):&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;$ easy_install PyCap&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You may notice another package, &lt;code class=&quot;highlighter-rouge&quot;&gt;requests&lt;/code&gt;, is installed as well.&lt;/p&gt;

&lt;p&gt;With installation out of the way, let’s start writing python. We’ll begin with
importing the package. The two main classes your scripts and applications should
use are the &lt;code class=&quot;highlighter-rouge&quot;&gt;Project&lt;/code&gt; class and the &lt;code class=&quot;highlighter-rouge&quot;&gt;RedcapError&lt;/code&gt; exception.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;redcap&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Project&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RedcapError&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;(As long as this import doesn’t fail, you installed &lt;code class=&quot;highlighter-rouge&quot;&gt;PyCap&lt;/code&gt; correctly).&lt;/p&gt;

&lt;h3 id=&quot;connecting-to-redcap-projects&quot;&gt;Connecting to REDCap Projects&lt;/h3&gt;

&lt;p&gt;Just like above, you’ll need to know your API token and URL for your site.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;project&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Project&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TOKEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;s (&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;s) ---&amp;gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;s&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'field_name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'field_type'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'field_label'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;study_id (text) ---&amp;gt; Study ID
first_name (text) ---&amp;gt; First Name
last_name (text) ---&amp;gt; Last Name
dob (text) ---&amp;gt; Date of Birth
sex (dropdown) ---&amp;gt; Gender
address (notes) ---&amp;gt; Street, City, State, ZIP
phone_number (text) ---&amp;gt; Phone number
file (file) ---&amp;gt; File
foo_score (text) ---&amp;gt; Test score for Foo test
bar_score (text) ---&amp;gt; Test score for Bar test
image_path (text) ---&amp;gt; image_path
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When you create a &lt;code class=&quot;highlighter-rouge&quot;&gt;Project&lt;/code&gt;, PyCap automatically exports the metadata from your
project. First, it does so to setup a few nice attributes on the object but more
importantly, if the metadata request works correctly, the URL and token are
correct and can be trusted to work later on.&lt;/p&gt;

&lt;p&gt;All of the methods the API provides are available. To demonstrate what we did
above, consider the following:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;export_metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;export_records&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'first_name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Billy Bob'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;import_records&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'count'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In these 5 lines, we:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Made an export metadata request (by default in json format), then
automatically decoded it.&lt;/li&gt;
  &lt;li&gt;Made a data export request (again, by default in JSON format) and returning
the decoded data.&lt;/li&gt;
  &lt;li&gt;Tweaked a single field of the first record.&lt;/li&gt;
  &lt;li&gt;Imported the new data.&lt;/li&gt;
  &lt;li&gt;Printing how many records were imported.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of the HTTP request machinery, making sure the payloads correct, encoding
and decoding the JSON responses is handled for you. I wrote PyCap because I
think most people just want their data and shouldn’t have to know HTTP to make
it happen. Trust me, I made a lot of mistakes in building this library. You
should use it so you don’t have to waste your time.&lt;/p&gt;

&lt;h3 id=&quot;file-downloadsuploadsdeletions&quot;&gt;File downloads/uploads/deletions&lt;/h3&gt;

&lt;p&gt;I didn’t really go through file actions above because every HTTP library is
going to deal with files differently. If you use PyCap, file operations are
super simple:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'1'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'file'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;export_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Just some data, you know.
data.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Obviously, most important returned data is the file contents. In the web-
application, the filename you see for this particular record/field is what comes
through in &lt;code class=&quot;highlighter-rouge&quot;&gt;headers['name']&lt;/code&gt;. So if you want to save it to your local hard
drive, it’s easy to keep the same name.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'w'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Just FYI, if you download a stored PDF, &lt;code class=&quot;highlighter-rouge&quot;&gt;contents&lt;/code&gt; will be the binary data
string and you’ll want to open the file in the &lt;code class=&quot;highlighter-rouge&quot;&gt;wb&lt;/code&gt; mode.&lt;/p&gt;

&lt;p&gt;Let’s say we want to upload a new file to that record. A little more
complicated, but still pretty easy.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;c&quot;&gt;# First write a new file&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'w'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Yeah, I decided to change the contents of the file'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;new_fname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'new_data.txt'&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'r'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;import_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_fname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# just to check...&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;export_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Yeah, I decided to change the contents of the file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And if you really want to delete a file from REDCap, that too is possible.
&lt;strong&gt;Warning&lt;/strong&gt; there is no undo button for this :)&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delete_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;There is more documentation for PyCap &lt;a href=&quot;http://sburns.github.io/PyCap&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;feedbackquestionscomments&quot;&gt;Feedback/Questions/Comments&lt;/h2&gt;

&lt;p&gt;Any feedback about this tutorial is greatly appreciated. There isn’t much on the
internet about this so I hope you find it helpful in your work with REDCap. Feel
free to open an issue on this post on &lt;a href=&quot;https://github.com/sburns/sburns.github.com&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>Legos & The Engineer's Brain</title>
        <link>http://sburns.org/2013/07/17/spatial-reasoning-legos.html</link>
        <pubDate>Wed, 17 Jul 2013 00:00:00 UTC</pubDate>
        <author></author>
        <guid>http://sburns.org/2013/07/17/spatial-reasoning-legos.html</guid>
        <description>&lt;p&gt;&lt;a href=&quot;http://news.vanderbilt.edu/2013/07/early-spatial-reasoning-predicts-later-creativity-and-innovation/&quot;&gt;Recent research&lt;/a&gt; from Vanderbilt (also in the &lt;a href=&quot;http://www.nytimes.com/2013/07/16/us/study-finds-early-signs-of-creativity-in-adults.html?_r=0&quot;&gt;NY Times&lt;/a&gt;) finds that performance on early (age 13) spatial reasoning tests increases the power to predict the student’s scholarly publications and patents some 30 years later above and beyond SAT mathematical and verbal scores alone:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The study, conducted by &lt;a href=&quot;https://my.vanderbilt.edu/smpy/publications/david-lubinski/&quot;&gt;David Lubinski&lt;/a&gt; and colleagues at &lt;a href=&quot;http://peabody.vanderbilt.edu/&quot;&gt;Vanderbilt University Peabody College of education and human development&lt;/a&gt;, provides evidence that early spatial ability – the skill required to mentally manipulate 2D and 3D objects – predicts the development of new knowledge, and especially innovation in science, technology, engineering and mathematics (STEM) domains, above and beyond more traditional measures of mathematical and verbal ability.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Obviously, the SAT score can predict future performance, especially in academic areas such as research publications and patent applications. Being an engineer by training, I find it interesting that spatial reasoning can increase the accuracy of these predictions. Engineers reason about systems on a day-to-day basis. Mechanical, chemical and civil engineers get to touch their creations; software engineers like myself must reason about the slightly less physical applications and distributed systems they create.&lt;/p&gt;

&lt;p&gt;I’ve theorized my more logical &amp;amp; analytical thought processes are directly (cor)related to my love for Legos as a child. I always built the designs described in the instructions first and only then would I get more creative with the pieces after I understood how they could fit together. The first page of the design only uses 3 or 4 pieces and it’s obvious how they join one another. Each successive step only differs by 3 or 4 pieces, but it’s not always obvious how (or why!) they assimilate into the previous state. Sometimes it was required to set down the current piece and start building a subsystem of the design. It was both magical and eye-opening when all of the pieces came together. Legos described a way for viewing and putting together the world different from any other toy in my childhood.&lt;/p&gt;

&lt;p&gt;That process alone, of determining the current state of a system, what it should be and how to get there most efficiently, is a near perfect overview of the field of engineering. I cannot wait to introduce Legos to my daughter!&lt;/p&gt;

&lt;p&gt;Without a doubt, working through this process over and over with Legos pushed my brain to hone these skills. Obviously, engineers face challenges that involve less plastic and more math, can be orders of magnitude more abstract and vary along more dimensions than just three; however, the foundation for thinking critically about systems both in their individual pieces and as a whole is critical to succeeding in the STEM fields.&lt;/p&gt;

</description>
      </item>
    
      <item>
        <title>Upcoming Kennedy Center Talk</title>
        <link>http://sburns.org/2013/07/12/upcoming-kc-talk.html</link>
        <pubDate>Fri, 12 Jul 2013 00:00:00 UTC</pubDate>
        <author></author>
        <guid>http://sburns.org/2013/07/12/upcoming-kc-talk.html</guid>
        <description>&lt;p&gt;I will be giving a talk for the Vanderbilt Kennedy Center’s Statistical and Methodology Core on Monday, July 22nd at 12:30p in One Magnolia Circle, Rm 241.&lt;/p&gt;

&lt;p&gt;The official calendar event &lt;a href=&quot;http://kc.vanderbilt.edu/site/newsandevents/calendar/page.aspx?id=3950&quot;&gt;can be found here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’ve given a “beta” version of this talk to a smaller audience at Chris Fonnesbeck’s Statistical Computing Series. I will discuss using advanced REDCap interfaces and how they can be leveraged to solve problems commonly faced in research.&lt;/p&gt;

&lt;p&gt;Because I’m expecting a very diverse audience, there are no code samples in the talk. I just finished a basic tutorial on using the REDCap API that can be found &lt;a href=&quot;http://bit.ly/pycap-tutorial&quot;&gt;here&lt;/a&gt;. You can see a very-close-to-the-actual-version of my slides &lt;a href=&quot;/assets/pdf/20130712-kc-redcap-beta.pdf&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There will be video at some point and I’ll post the link somewhere around here.&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>Freesurfer Stats in REDCap</title>
        <link>http://sburns.org/2013/07/10/freesurfer-stats-in-redcap.html</link>
        <pubDate>Wed, 10 Jul 2013 00:00:00 UTC</pubDate>
        <author></author>
        <guid>http://sburns.org/2013/07/10/freesurfer-stats-in-redcap.html</guid>
        <description>&lt;p&gt;&lt;a href=&quot;http://surver.nmr.mgh.harvard.edu&quot;&gt;Freesurfer&lt;/a&gt; is a fantastic software package for reconstructing the brain’s cortical surface from a high resolution structural MR image. Just give it a T1-weighted image (where gray matter is gray, white matter white) and a day of processing time (depending on image quality) and it produces 3D meshes of the white and gray matter surfaces. Given these models, it can then do all sorts of fancy calculations like area and average cortical thickness of particular regions. It’s a fantastic tool for researchers because manual delineation of the cortical surface requires expertise and is extremely time-intensive. It’s not an option when you’re collecting data from one or two subjects a day as we do in our lab.&lt;/p&gt;

&lt;p&gt;The problem with Freesurfer is that it can be extremely verbose with the data it spits out. We want to put these statistics into our REDCap databases so we can better analyze them against the myriad of behavioral measures we collect. If you run Freesurfer and generate advanced labeling, it can produce upwards of 2700 measures per subject. It’s simply untenable to make some poor RA copy/paste all of these values into REDCap.&lt;/p&gt;

&lt;p&gt;So, to make this sort of thing easier, I wrote a little tool that parses and flattens the stats files into a simple python dictionary. Usage goes a little something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;recon_stats&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Subject&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'SUBJECTID'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# where SUBJECTID is an identifier for a subject living in SUBJECTS_DIR&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_measures&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upload_dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Using my PyCap package, you can then import the data into a REDCap project&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;redcap&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Project&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Project&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TOKEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;def_field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'SUBJECTID'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;import_records&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This isn’t going to work until you’ve added the ~2650 fields to your REDCap data dictionary which is no task for the faint of heart. To make this a little more easier for everyone, I created a &lt;a href=&quot;http://www.project-redcap.org/library/&quot;&gt;REDCap Shared Library&lt;/a&gt; so anyone with a REDCap project can easily search for &lt;code class=&quot;highlighter-rouge&quot;&gt;Freesurfer Reconstruction Stats&lt;/code&gt; and download it into their project’s data dictionary. Doing will will create a &lt;code class=&quot;highlighter-rouge&quot;&gt;recon&lt;/code&gt; form. I don’t recommend viewing this form for any particular record in your project, REDCap takes quite a while to generate HTML for all 2655 fields :)&lt;/p&gt;

&lt;p&gt;Check out &lt;a href=&quot;https://github.com/sburns/recon-stats&quot;&gt;the repo on github&lt;/a&gt;. It’s on my to-do list to put it up on PyPI. Until then you can &lt;code class=&quot;highlighter-rouge&quot;&gt;git clone&lt;/code&gt; the repo to your local machine. Happy &lt;code class=&quot;highlighter-rouge&quot;&gt;recon-all&lt;/code&gt; &amp;amp; REDCap’ing!&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>There aren't unit tests for opinions</title>
        <link>http://sburns.org/2013/01/24/no-unittests-for-opinions.html</link>
        <pubDate>Thu, 24 Jan 2013 00:00:00 UTC</pubDate>
        <author></author>
        <guid>http://sburns.org/2013/01/24/no-unittests-for-opinions.html</guid>
        <description>&lt;p&gt;I spend the majority of my day attempting to convince my computer that I’m not an idiot. Some days I’m more successful than others.&lt;/p&gt;

&lt;p&gt;One way to help improve this process is to write software in such a way that it can be &lt;a href=&quot;http://en.wikipedia.org/wiki/Unit_testing&quot;&gt;unit tested&lt;/a&gt;. Unit testing involves ensuring the building blocks of your code operate as you expect on predetermined inputs and outputs. If you test well enough, you can rest assured that your code is doing what you think it is doing and more importantly what you want it to do. You might say untested code is inherently wrong because you can’t &lt;em&gt;trust&lt;/em&gt; it.&lt;/p&gt;

&lt;p&gt;Unfortunately, there is no unit testing framework for opinions. There is no magic to automatically check the veracity and intent of a thought or statement. This is made worse by the expanse to which we can share our ideas these days.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Just because you can type or say it doesn’t make it correct&lt;/strong&gt;. We take other people being wrong to imply naiveté (but too often we jump straight to stupidity) in our society. I wish it meant something more akin to having a unit test fail and that they should try again.&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>Winter Pesto</title>
        <link>http://sburns.org/2013/01/22/winter-pesto.html</link>
        <pubDate>Tue, 22 Jan 2013 00:00:00 UTC</pubDate>
        <author></author>
        <guid>http://sburns.org/2013/01/22/winter-pesto.html</guid>
        <description>&lt;p&gt;I made my own pesto the other night and am kicking myself for waiting this long to do so:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;a large handful of spinach, chopped coarsely&lt;/li&gt;
  &lt;li&gt;2/3 cup walnuts, preferably roasted&lt;/li&gt;
  &lt;li&gt;2 cloves garlic&lt;/li&gt;
  &lt;li&gt;salt and pepper to taste&lt;/li&gt;
  &lt;li&gt;1/3 cup extra virgin olive oil&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add the garlic, nuts, salt, pepper, and about a third of the spinach to a food processor and pulse to a coarse mix. Add the rest of the spinach (or in batches as much as your processor can handle) and chop. Add the oil in parts and if you have some liquid available (from cooking pasta perhaps) add some now. &lt;em&gt;Note&lt;/em&gt;, the liquid will assist in chopping so the more liquid, the finer the pesto. A quarter cup makes for a thin pesto.&lt;/p&gt;

&lt;p&gt;Toss with pasta, top with good parmesan and enjoy.&lt;/p&gt;
</description>
      </item>
    
      <item>
        <title>Hell is Other People's Spreadsheets</title>
        <link>http://sburns.org/2013/01/21/hell-is-spreadsheets.html</link>
        <pubDate>Mon, 21 Jan 2013 00:00:00 UTC</pubDate>
        <author></author>
        <guid>http://sburns.org/2013/01/21/hell-is-spreadsheets.html</guid>
        <description>&lt;p&gt;When I started at &lt;a href=&quot;http://kc.vanderbilt.edu/educationandbrainlab/&quot; title=&quot;Education and Brain Research Lab&quot;&gt;EBRL&lt;/a&gt;, we had begun slowly moving to capturing and recording all subject data in &lt;a href=&quot;http://project-redcap.org&quot; title=&quot;Project REDCap&quot;&gt;various REDCap projects&lt;/a&gt;. REDCap is web-based data capture system created by the &lt;a href=&quot;https://victr.vanderbilt.edu/pub/&quot; title=&quot;VICTR&quot;&gt;Vanderbilt Institute for Clinical and Translational Research&lt;/a&gt;. Briefly, REDCap allows clinical and scientific groups to build, operate and use databases all through a web application. Without REDCap, these types of groups have either captured data in difficult-to-maintain spreadsheets or hire/outsource the development and admnistration of a database system. Both alternatives are frought with danger (especially when capturing personal health information (PHI)) and specifically for our lab, moving to REDCap was advantageous for the following reasons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;No more emailing spreadsheets (especially those containing PHI).&lt;/li&gt;
  &lt;li&gt;One and only one place to monitor subject status.&lt;/li&gt;
  &lt;li&gt;One and only one place from which to start analyses.&lt;/li&gt;
  &lt;li&gt;No more emailing spreadsheets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Slowly but surely, we’ve created enough databases such that no data captured in our lab is canonically stored in a spreadsheet. Our data is more safe, more accessible, and more pliable in that REDCap can export formats understood by many statistical packages.&lt;/p&gt;

&lt;p&gt;These advantages only scratch the surface of what putting our data in REDCap meant. Because REDCap exposes an Application Programming Interface (API) for exporting and importing data, it doesn’t take much to realize that we could automate some of the more tedious and error-prone data workflows.&lt;/p&gt;

&lt;p&gt;In future posts I will expound upon some of the technology and infrastructure I’ve developed for the lab, how it relates to REDCap, and ultimately how it has enabled us to produce more reliable and better science.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Take home message&lt;/strong&gt;: From our perspective, if data is not in a globally and programmatically accessible place, it might as well not exist.&lt;/p&gt;
</description>
      </item>
    
  </channel>
</rss>