1

I inherited a complicated Snakemake setup. It uses a configfile that contains

{
  "sub": [
    1234,
  ],
  "ses": [
    "1"
  ],
  "task": [
    "fake"
  ],
  "run": [
    "1"
  ],
  "acq": [
    "mb"
  ],

  "bids_dir": "../../bids"

In the all recipe, it uses for input calls to expand() that look like this.

expand('data/{task}/preproc/acq-{acq}/sub-{sub}/ses-{ses}/run-{run}/bold.nii', **config)

Then, I have a recipe that looks like this:

rule getRawFunc:
    input:
        rawFunc = config['bids_dir'] + '/sub-{sub}/ses-{ses}/func/sub-{sub}_ses-{ses}_task-{task}_acq-{acq}_run-{run}_bold.nii.gz'
    output:
        func = temp('data/{task}/preproc/acq-{acq}/sub-{sub}/ses-{ses}/run-{run}/bold.nii')
    shell:
        'gunzip -c {input} > {output}'

I am not understanding why it needs config['bids_dir'] to get the value for that, but it seemingly does not need that to expand the values for {sub} and the like.

I looked at the section about expand at

https://snakemake.readthedocs.io/en/latest/snakefiles/configuration.html#standard-configuration

and that and the tutorials explain the use of config['bids_dir'] well, it's just that **config that I am not quite getting.

Further explication would be most appreciated!

SultanOrazbayev
  • 14,900
  • 3
  • 16
  • 46
Bennet
  • 11
  • 1

1 Answers1

1

In general expand function requires the template and keyword arguments to use when filling in the template, like so:

expand('{a}_{b}', a='some', b='test')
# this will return 'some_test'

Now, in Python one can do dictionary unpacking by placing two asterisks before the dictionary '**some_dict'. What this does is unpack the contents of the dictionary as 'key=value'. In the example above, we can get the same result by unpacking a dictionary:

some_dict = {'a': 'some', 'b': 'test'}
expand('{a}_{b}', **some_dict)
# this will return 'some_test'

You can read more details in this answer.

SultanOrazbayev
  • 14,900
  • 3
  • 16
  • 46