Skip to content

Commit f6fb767

Browse files
committed
NF - add get/set for sform/qform on image
Following same signatures for new header qform / sform get / set, but adding update_affine keyword only keyword.
1 parent bb5d1da commit f6fb767

File tree

1 file changed

+164
-0
lines changed

1 file changed

+164
-0
lines changed

nibabel/nifti1.py

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,6 +1589,170 @@ def update_header(self):
15891589
# Make qform 'unknown'
15901590
hdr.set_qform(self._affine, code='unknown')
15911591

1592+
def get_qform(self, coded=False):
1593+
""" Return 4x4 affine matrix from qform parameters in header
1594+
1595+
Parameters
1596+
----------
1597+
coded : bool, optional
1598+
If True, return {affine or None}, and qform code. If False, just
1599+
return affine. {affine or None} means, return None if qform code ==
1600+
0, and affine otherwise.
1601+
1602+
Returns
1603+
-------
1604+
affine : None or (4,4) ndarray
1605+
If `coded` is False, always return affine reconstructed from qform
1606+
quaternion. If `coded` is True, return None if qform code is 0,
1607+
else return the affine.
1608+
code : int
1609+
Qform code. Only returned if `coded` is True.
1610+
1611+
See also
1612+
--------
1613+
Nifti1Header.set_qform
1614+
"""
1615+
return self._header.get_qform(coded)
1616+
1617+
def set_qform(self, affine, code=None, strip_shears=True, **kwargs):
1618+
''' Set qform header values from 4x4 affine
1619+
1620+
Parameters
1621+
----------
1622+
hdr : nifti1 header
1623+
affine : None or 4x4 array
1624+
affine transform to write into sform. If None, only set code.
1625+
code : None, string or integer
1626+
String or integer giving meaning of transform in *affine*.
1627+
The default is None. If code is None, then:
1628+
* If affine is None, `code`-> 0
1629+
* If affine not None and sform code in header == 0, `code`-> 2
1630+
(aligned)
1631+
* If affine not None and sform code in header != 0, `code`-> sform
1632+
code in header
1633+
strip_shears : bool, optional
1634+
Whether to strip shears in `affine`. If True, shears will be
1635+
silently stripped. If False, the presence of shears will raise a
1636+
``HeaderDataError``
1637+
update_affine : bool, optional
1638+
Whether to update the image affine from the header best affine after
1639+
setting the qform. Must be keyword argumemt (because of different
1640+
position in `set_qform`). Default is True
1641+
1642+
See also
1643+
--------
1644+
Nifti1Header.set_qform
1645+
1646+
Examples
1647+
--------
1648+
>>> data = np.arange(24).reshape((2,3,4))
1649+
>>> aff = np.diag([2, 3, 4, 1])
1650+
>>> img = Nifti1Pair(data, aff)
1651+
>>> img.get_qform()
1652+
array([[ 2., 0., 0., 0.],
1653+
[ 0., 3., 0., 0.],
1654+
[ 0., 0., 4., 0.],
1655+
[ 0., 0., 0., 1.]])
1656+
>>> img.get_qform(coded=True)
1657+
(None, 0)
1658+
>>> aff2 = np.diag([3, 4, 5, 1])
1659+
>>> img.set_qform(aff2, 'talairach')
1660+
>>> qaff, code = img.get_qform(coded=True)
1661+
>>> np.all(qaff == aff2)
1662+
True
1663+
>>> int(code)
1664+
3
1665+
'''
1666+
update_affine = kwargs.pop('update_affine', True)
1667+
if kwargs:
1668+
raise TypeError('Unexpected keyword argument(s) %s' % kwargs)
1669+
self._header.set_qform(affine, code, strip_shears)
1670+
if update_affine:
1671+
self._affine[:] = self._header.get_best_affine()
1672+
1673+
def get_sform(self, coded=False):
1674+
""" Return 4x4 affine matrix from sform parameters in header
1675+
1676+
Parameters
1677+
----------
1678+
coded : bool, optional
1679+
If True, return {affine or None}, and sform code. If False, just
1680+
return affine. {affine or None} means, return None if sform code ==
1681+
0, and affine otherwise.
1682+
1683+
Returns
1684+
-------
1685+
affine : None or (4,4) ndarray
1686+
If `coded` is False, always return affine from sform fields. If
1687+
`coded` is True, return None if sform code is 0, else return the
1688+
affine.
1689+
code : int
1690+
Sform code. Only returned if `coded` is True.
1691+
1692+
See also
1693+
--------
1694+
Nifti1Header.get_sform
1695+
"""
1696+
return self._header.get_sform(coded)
1697+
1698+
def set_sform(self, affine, code=None, **kwargs):
1699+
''' Set sform transform from 4x4 affine
1700+
1701+
Parameters
1702+
----------
1703+
hdr : nifti1 header
1704+
affine : None or 4x4 array
1705+
affine transform to write into sform. If None, only set `code`
1706+
code : None, string or integer
1707+
String or integer giving meaning of transform in *affine*.
1708+
The default is None. If code is None, then:
1709+
* If affine is None, `code`-> 0
1710+
* If affine not None and sform code in header == 0, `code`-> 2
1711+
(aligned)
1712+
* If affine not None and sform code in header != 0, `code`-> sform
1713+
code in header
1714+
update_affine : bool, optional
1715+
Whether to update the image affine from the header best affine after
1716+
setting the qform. Must be keyword argumemt (because of different
1717+
position in `set_qform`). Default is True
1718+
1719+
See also
1720+
--------
1721+
Nifti1Header.set_sform
1722+
1723+
Examples
1724+
--------
1725+
>>> data = np.arange(24).reshape((2,3,4))
1726+
>>> aff = np.diag([2, 3, 4, 1])
1727+
>>> img = Nifti1Pair(data, aff)
1728+
>>> img.get_sform()
1729+
array([[ 2., 0., 0., 0.],
1730+
[ 0., 3., 0., 0.],
1731+
[ 0., 0., 4., 0.],
1732+
[ 0., 0., 0., 1.]])
1733+
>>> saff, code = img.get_sform(coded=True)
1734+
>>> saff
1735+
array([[ 2., 0., 0., 0.],
1736+
[ 0., 3., 0., 0.],
1737+
[ 0., 0., 4., 0.],
1738+
[ 0., 0., 0., 1.]])
1739+
>>> int(code)
1740+
2
1741+
>>> aff2 = np.diag([3, 4, 5, 1])
1742+
>>> img.set_sform(aff2, 'talairach')
1743+
>>> saff, code = img.get_sform(coded=True)
1744+
>>> np.all(saff == aff2)
1745+
True
1746+
>>> int(code)
1747+
3
1748+
'''
1749+
update_affine = kwargs.pop('update_affine', True)
1750+
if kwargs:
1751+
raise TypeError('Unexpected keyword argument(s) %s' % kwargs)
1752+
self._header.set_sform(affine, code)
1753+
if update_affine:
1754+
self._affine[:] = self._header.get_best_affine()
1755+
15921756

15931757
class Nifti1Image(Nifti1Pair):
15941758
header_class = Nifti1Header

0 commit comments

Comments
 (0)