Fitlins group level model

Hello! I’m trying out FitLins for the first time. I’m getting beautiful subject level models, but for the life of me cannot get group level average (I just get blank glass brains). I’ve based my model off of the “Word vs Pseudoword” example. Of note:

  • There are 3 conditions: forward, backward, and dichotic. My two contrasts of interest are forward > backward, and dichotic > forward.
  • Each participant has one run in each of two sessions (pre and post). I would like group averages separated by session and contrast (so, each contrast at time pre, and each contrast at time post).

Please and thank you in advance!

{
   "Name":"story_model001",
   "BIDSModelVersion":"1.0.0",
   "Description":"dichotic language localizer",
   "Input":{
      "task":"story"
   },
   "Nodes":[
      {
         "Level":"run",
         "Name":"subject",
         "GroupBy":[
            "subject",
            "session"
         ],
         "Transformations":{
            "Transformer":"pybids-transforms-v1",
            "Instructions":[
               {
                  "Name":"Factor",
                  "Input":[
                     "trial_type"
                  ]
               },
               {
                  "Name":"Convolve",
                  "Input":[
                     "trial_type.dichotic",
                     "trial_type.forward",
                     "trial_type.backward"
                  ],
                  "Model":"spm"
               }
            ]
         },
         "Model":{
            "X":[
               "trial_type.dichotic",
               "trial_type.forward",
               "trial_type.backward",
               "framewise_displacement",
               "trans_x",
               "trans_y",
               "trans_z",
               "rot_x",
               "rot_y",
               "rot_z",
               "a_comp_cor_00",
               "a_comp_cor_01",
               "a_comp_cor_02",
               "a_comp_cor_03",
               "a_comp_cor_04",
               "a_comp_cor_05",
               1
            ]
         },
         "DummyContrasts":{
            "Conditions":[
               "trial_type.dichotic",
               "trial_type.forward",
               "trial_type.backward"
            ],
            "Test":"t"
         },
         "Contrasts":[
            {
               "Name":"dichotic_gt_forward",
               "ConditionList":[
                  "trial_type.dichotic",
                  "trial_type.forward"
               ],
               "Weights":[
                  1,
                  -1
               ],
               "Test":"t"
            },
            {
              "Name":"forward_gt_backward",
              "ConditionList":[
                "trial_type.forward",
                "trial_type.backward"
              ],
              "Weights":[
                1,
                -1
              ],
              "Test":"t"
            },
            {
               "Name":"task_vs_baseline",
               "ConditionList":[
                  "trial_type.dichotic",
                  "trial_type.forward",
                  "trial_type.backward"
               ],
               "Weights":[
                  0.33,
                  0.33,
                  0.33
               ],
               "Test":"t"
            }
         ]
      },
      {
         "Level":"dataset",
         "Name":"t-test",
         "GroupBy":[
            "session",
            "contrast"
         ],
         "Model":{
            "X":[
               1
            ],
            "Type":"glm"
         },
         "DummyContrasts":{
            "Test":"t"
         }
      },
      {
         "Level":"dataset",
         "Name":"F-test",
         "GroupBy":[
	    "session"
         ],
         "Model":{
            "X":[
                "trial_type.dichotic",
                "trial_type.forward",
                "trial_type.backward"
            ],
            "Type":"glm"
         },
         "Contrasts":[
            {
               "Name":"group",
               "ConditionList":[
                  "trial_type.dichotic",
                  "trial_type.forward",
                  "trial_type.backward"
               ],
               "Weights":[
                  [
                     1,
                     0,
                     0
                  ],
                  [
                     0,
                     1,
                     0
                  ],
                  [
                     0,
                     0,
                     1
                  ]
               ],
               "Test":"F"
            }
         ]
      }
   ],
   "Edges":[
      {
         "Source":"subject",
         "Destination":"t-test",
         "Filter":{
            "contrast":[
               "dichotic_gt_forward",
               "forward_gt_backward",
               "task_vs_baseline"
            ]
         }
      },
      {
         "Source":"subject",
         "Destination":"F-test",
         "Filter":{
            "contrast":[
               "trial_type.dichotic",
               "trial_type.forward",
               "trial_type.backward"
            ]
         }
      }
   ]
}

Hello,

One question first: Are there multiple runs for each subject? That is, within each session.

At first glance, your model looks good to me. Typically we GroupBy run in the first level, but if you only have one run per session this should be fine

Hi @Rachel_Romeo and welcome to neurostars!

Not quite an answer but I will note that if you use acompcor components, you should also include the cosine regressors in your model! So you can add cosine* to your model covariates.

Also, I think you need to add an edge to make outputs available from subject to group nodes.

Best,
Steven

The bids stats model validator has a few warnings:
https://bids-standard.github.io/stats-models/validator.html

.Input.task must be array
.Nodes[0].Level should be equal to one of: Run, Session, Subject, Dataset
.Nodes[0].Model must have required property ‘Type’
.Nodes[0].DummyContrasts should NOT have additional property: Conditions
.Nodes[1].Level should be equal to one of: Run, Session, Subject, Dataset
.Nodes[2].Level should be equal to one of: Run, Session, Subject, Dataset

But I think that if they had been an issue for fitlins you would have seen some other type of problems and earlier than that.

That part looks actually correct to me.

The model has 3 nodes: 1 run level node and 2 datasets level nodes. It has 2 edges that connect the run level node to each dataset level node.

Yah, I see that now, I had confused the run level (group) and node name (F-test)

1 Like

Thanks! Only one run per subject, but I can still add Group By run if there’s no harm.

Not quite an answer but I will note that if you use acompcor components, you should also include the cosine regressors in your model! So you can add cosine* to your model covariates.

Thanks! What are current recommendations overall for the specific regressors to include? If relevant, these are young children who wiggle a bit.

No golden bullet at the moment, especially because most denoising benchmarks have focused on resting state and not task GLMs. I think what you have is fine after adding the cosine regressors. Although I am a bit puzzled by including the head motion parameters and FD.

In your fitlins command, you will not need to account for drift anymore (if that is something you were doing already) since the cosine regressors high pass filter the data at (1/128) Hz.

Best,
Steven

Clarification – you’re puzzled by BOTH head motion parameters AND FD (as in, only one is sufficient), or puzzled by inclusion of either of them?

Sorry haha, the inclusion of both of them TOGETHER. It seems like FD would be some linear combination of motion parameters, so I am not sure of what it is adding.

Yes, you could try only doing GroupBy : ["subject", "run"] at the first level, which should be an equivalent model, but is closer to what we typically do (if this works, this indicates a bug in FitLins).

I showed your model to some colleagues and we couldn’t find anything wrong.

One thing you could try is to remove the Edges all together, since the X in Model for the dataset level acts a filter anyways.

If you don’t define any Edges, all levels are linked sequentially by level.

If that doesn’t work, we might have to see if there’s a FitLins bug happening here.

Just to confirm – we have "Level":"run" – is it a problem to have both Level and GroupBy include run?
For what it’s worth, having different “sessions” has been a big pain, since most default code only has one session (sigh).

No, that’s not a problem.

That’s good feedback though, we should definitely add an example like yours to the gallery.

Level primarily determines where to look for input data. So "Level":"run" means that variables for the design matrix will be from _events.tsv, whereas in higher levels you may want variables from _participants.tsv

See: Legacy specification — BIDS Stats Models Specification

On the other hand, GroupBy specifies how inputs are grouped. For the first level, you typically want to group by ['run', 'subject'] because that ensures that every run for every subject is analyzed separately.
In your case, since you only have one run per session, the way you specified it should be identical.

Going back to debugging your issue, when you look in the output folder, what files are written out under the dataset level output folder?

Going back to debugging your issue, when you look in the output folder, what files are written out under the dataset level output folder?

I have a folder for node-Ftest, with subfolders for ses-pre and ses-post, and those contain nifti files for effect, p, t, variance, & z statmaps, but they are all blank.

Is this the same for node-t-test?

I’m trying to see if I can develop a similar model on pybids test data, to see if there’s a bug, and if there is, fix it and, add this to the tests

I actually don’t have a folder for node-t-test. What I do have is node-subject and that’s where all the good subject-level output is

Okay, I made a similar model on a test dataset, and pybids had no problem grouping by session either at the run or dataset level. I can only think this is a bug with something other than your model.

I can suggest two things at the moment:

  1. Let’s move this to the fitlins github repo and open a issue. It’s going to be hard to debug w/o at least a sample of your data (for at least 2 subjects), so if you’re willing to provide that, that’d be great.
    Please confirm your FitLins version
  1. In the meantime, here’s two things you could try:
  • change GroupBy at in first node to : ['run', 'subject']. Shouldn’t need to but it could be a bug.
  • You could also try to remove session from GroupBy at the dataset level, and instead add a “filter” to limit the node to a single session:
      {
        "Source":"subject",
        "Destination":"t-test-2",
        "Filter":{
           "contrast":[
              "dichotic_gt_forward",
              "forward_gt_backward",
              "task_vs_baseline"
           ],
           "session": "02"
        }

If this works, then it indicates a bug, but you can at least get your results in the meantime by doubling the nodes at the dataset level (on for each level of “session”)