<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=utf-8">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <div dir="ltr">
      <div>So, if nibabel reads and write everything correctly, must be
        something down the fsl path doing non cool stuff. Question now
        is if I should bother fixing it and risk breaking stuff for
        other people as unseen side effects.<br>
      </div>
      At least I learned stuff, had no idea qform can not store all
      possible transformations, so that explains why it differs slightly
      from the sform after saving back.<br>
      <br>
      ---------<br>
      <br>
      And one week later (this above was an earlier draft) I got around
      to actually fix it, but I cannot explain why. If I save back the
      header with it, I do not experience the flip. If I tell nibabel to
      create an header because I did not pass anything, it seems to put
      back my data in RAS (think I saw this on the website, but I though
      it was only for internal representation).<br>
      <br>
      So, saving back header + I change the dtype manually (since the
      dtype from the header is used, which is almost always int16 to
      float32 for me) does not flip anything. Although I still can't
      figure out why the created header gives me flipped data, here is a
      small excerpt of said header.<br>
      <br>
      Nibabel saved back original header<br>
      <br>
      qform_name     Scanner Anat<br>
      qform_code     1<br>
      qto_xyz:1      -1.796652  0.000000  -0.000000  112.420448<br>
      qto_xyz:2      0.000000  1.795833  -0.054337  -90.885376<br>
      qto_xyz:3      0.000000  0.054236  1.799180  54.572971<br>
      qto_xyz:4      0.000000  0.000000  0.000000  1.000000<br>
      qform_xorient  Right-to-Left<br>
      qform_yorient  Posterior-to-Anterior<br>
      qform_zorient  Inferior-to-Superior<br>
      sform_name     Scanner Anat<br>
      sform_code     1<br>
      sto_xyz:1      -1.796652  0.000000  0.000000  112.420448<br>
      sto_xyz:2      0.000000  1.795833  -0.054337  -90.885376<br>
      sto_xyz:3      0.000000  0.054236  1.799180  54.572971<br>
      sto_xyz:4      0.000000  0.000000  0.000000  1.000000<br>
      sform_xorient  Right-to-Left<br>
      sform_yorient  Posterior-to-Anterior<br>
      sform_zorient  Inferior-to-Superior<br>
      <br>
      Nibabel recreated header<br>
      <br>
      <br>
      qform_name     Unknown<br>
      qform_code     0<br>
      qto_xyz:1      1.796652  0.000000  0.000000  0.000000<br>
      qto_xyz:2      0.000000  1.796652  0.000000  0.000000<br>
      qto_xyz:3      0.000000  0.000000  1.800000  0.000000<br>
      qto_xyz:4      0.000000  0.000000  0.000000  1.000000<br>
      qform_xorient  Left-to-Right<br>
      qform_yorient  Posterior-to-Anterior<br>
      qform_zorient  Inferior-to-Superior<br>
      sform_name     Aligned Anat<br>
      sform_code     2<br>
      sto_xyz:1      -1.796652  0.000000  0.000000  112.420448<br>
      sto_xyz:2      0.000000  1.795833  -0.054337  -90.885376<br>
      sto_xyz:3      0.000000  0.054236  1.799180  54.572971<br>
      sto_xyz:4      0.000000  0.000000  0.000000  1.000000<br>
      sform_xorient  Right-to-Left<br>
      sform_yorient  Posterior-to-Anterior<br>
      sform_zorient  Inferior-to-Superior<br>
      <br>
      <br>
    </div>
    <div class="gmail_extra">Notice how the qform has shearing in the
      first case (and original also), while it has flipped orientation
      and no shearing in the recreated header case.<br>
      So, two questions : <br>
      - Is there any adverse effect to using original headers if I know
      for certain nothing changed except dtype?<br>
      - Well, I still can't figure out the flipping (is it the same when
      transformation would be applied in world space? So it still is
      flipped for all software in image space in this case then) <br>
      or is that some nibabel RAS convention? I am still confused as to
      what happened to the orientation for the recreated header.<br>
      <br>
      Samuel<br>
      <br>
      P.S. Quick snippet to reproduce flipping with fslorient, adapt
      filename of course but any random nifti should work, this was
      diffusion data. Check header with fslhd afterwards.<br>
      <br>
      fslorient -swaporient 'out.nii.gz'<br>
      <br>
      In [1]: import nibabel as nib<br>
      <br>
      In [3]: vol=nib.load('out.nii.gz')<br>
      <br>
      In [4]: data=vol.get_data()<br>
      <br>
      In [5]: aff=vol.get_affine()<br>
      <br>
      In [6]: hdr=vol.get_header()<br>
      <br>
      In [7]: nib.save(nib.Nifti1Image(data,aff,hdr),'out2.nii.gz')<br>
      <br>
      In [8]: nib.save(nib.Nifti1Image(data,aff),'out3.nii.gz')<br>
      <br>
      <br>
      <div class="gmail_quote">2016-06-28 15:13 GMT+02:00 Matthew Brett
        <span dir="ltr"><<a href="mailto:matthew.brett@gmail.com"
            target="_blank">matthew.brett@gmail.com</a>></span>:<br>
        <blockquote class="gmail_quote" style="margin:0 0 0
          .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
          <span class=""><br>
            On Mon, Jun 27, 2016 at 11:50 PM, Samuel St-Jean <<a
              href="mailto:stjeansam@gmail.com">stjeansam@gmail.com</a>>
            wrote:<br>
            > I'll need to play a bit with it today and ask some guy
            about the flipping, I<br>
            > am reporting for someone else actually. So, it seems to
            be harmless to put<br>
            > back the header in the case of unchanged affine (as it
            is in my situation),<br>
            > could be that other software downstream does not really
            like something else.<br>
            > I did not reuse it because of dtypes, voxelsize and
            other things which may<br>
            > wildly change on processed data.<br>
            ><br>
            ><br>
            > Anyway, this example is using your case number 1, no
            header, affine is<br>
            > gotten from get_affine. Of course it was not modified
            during the processing,<br>
            > and I end up with a different sform/qform. Accoridng to
            your first point, I<br>
            > expected them to be identical, but I end up with a
            sligthly different (and<br>
            > diagonal) qform. They also have different names, so
            ifthey were set to the<br>
            > same thing I would expect them to be pristine copies.<br>
            ><br>
            > That's a bit troublesome now as JC pointed out, since
            we all use the same<br>
            > set of scripts for the  heavy processing, which don't
            reuse headers as I can<br>
            > remember. Does not seem to cause any problem for us,
            don't want to receive<br>
            > hate mail by other people using some of our stuff and
            saying we broke their<br>
            > data though.<br>
            ><br>
            > Are sform and qform set to match the affine in exactly
            the same way, or does<br>
            > some transformation is applied and then they are
            identical? I went through<br>
            > the info on the nibabel website about headers and
            affine, so maybe I just<br>
            > missed it also if anyone has other info to add.<br>
            <br>
          </span>Well - remember that the qform is stored differently
          from the sform.<br>
          In particular, the qform cannot store shears, because it's the<br>
          composition of the translations on a pure rotation on the
          zooms,<br>
          whereas the sform can, because it stores a full 3 x 4 affine
          matrix.<br>
          <br>
          The sform and the qform will have different so-called
          "transform<br>
          codes", if the sform and qform both get set (rules as
          described in my<br>
          last email).  This is because the default transform codes are<br>
          different for the sform and qform, and we use the defaults.<br>
          <br>
          The flip should always be the same though, when the sform and
          qform<br>
          get set together - at least if the external software is
          reading the<br>
          header correctly.<br>
          <div class="HOEnZb">
            <div class="h5"><br>
              Cheers,<br>
              <br>
              Matthew<br>
              _______________________________________________<br>
              Neuroimaging mailing list<br>
              <a href="mailto:Neuroimaging@python.org">Neuroimaging@python.org</a><br>
              <a
                href="https://mail.python.org/mailman/listinfo/neuroimaging"
                rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/neuroimaging</a><br>
            </div>
          </div>
        </blockquote>
      </div>
      <br>
    </div>
  </body>
</html>