Skip to content

Commit

Permalink
Merge pull request #222 from vinferrer/bids_units
Browse files Browse the repository at this point in the history
Add BIDS-compatible automatic reformatting of units of measure
  • Loading branch information
rmarkello authored Jun 2, 2020
2 parents d7ffcb0 + d068faf commit a60e951
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 0 deletions.
84 changes: 84 additions & 0 deletions phys2bids/bids_units.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import logging

LGR = logging.getLogger(__name__)

unit_aliases = {
# kelvin: thermodynamic temperature
'k': 'K', 'kelvin': 'K', 'kelvins': 'K',
# mole: amount of substance
'mol': 'mol', 'mole': 'mol',
# newton: force, weight
'newton': 'N', 'newtons': 'N', 'n': 'N',
# pascal: pressure, stress
'pascal': 'Pa', 'pascals': 'Pa', 'pa': 'Pa',
# volt: voltage (electrical potential), emf
'v': 'V', 'volt': 'V', 'volts': 'V',
# degree Celsius: temperature relative to 273.15 K
'°c': '°C', '°celsius': '°C', 'celsius': '°C',
# ampere: electric current
'a': 'A', 'ampere': 'A', 'amp': 'A', 'amps': 'A',
# second: time and hertzs
'1/hz': 's', '1/hertz': 's', 'hz': 'Hz',
'1/s': 'Hz', '1/second': 'Hz', '1/seconds': 'Hz',
'1/sec': 'Hz', '1/secs': 'Hz', 'hertz': 'Hz',
'second': 's', 'seconds': 's', 'sec': 's',
'secs': 's', 's': 's',
}

# Init dictionary of aliases for multipliers. Entries are still lowercase
prefix_aliases = {
# Multiples - skip "mega" and only up to "tera"
'da': 'da', 'deca': 'da', 'h': 'h', 'hecto': 'h',
'k': 'k', 'kilo': 'k', 'g': 'G', 'giga': 'G', 't': 'T',
'tera': 'T',
# Submultipliers
'd': 'd', 'deci': 'd', 'c': 'c', 'centi': 'c',
'milli': 'm', 'm': 'm', 'µ': 'µ', 'micro': 'µ',
'n': 'n', 'nano': 'n', 'p': 'p', 'pico': 'p',
'f': 'f', 'femto': 'f', 'a': 'a', 'atto': 'a',
'z': 'z', 'zepto': 'z', 'y': 'y', 'yocto': 'y',
}


def bidsify_units(orig_unit):
"""
Read the input unit of measure and use the dictionary of aliases
to bidsify its value.
It is possible to make simple conversions
Parameters
----------
unit: string
Unit of measure, might or might not be BIDS compliant.
Returns
-------
new_unit: str
BIDSified alias of input unit
Notes
-----
This function should implement a double check, one for unit and
the other for prefixes (e.g. "milli"). However, that is going to be tricky,
unless there is a weird way to multiply two dictionaries together.
"""
# call prefix and unit dicts
# for every unit alias in the dict
orig_unit = orig_unit.lower()
for u_key in unit_aliases.keys():
if orig_unit.endswith(u_key):
new_unit = unit_aliases[u_key]
unit = orig_unit[:-len(u_key)]
if unit != '':
# for every prefix alias
prefix = prefix_aliases.get(unit, '')
if prefix == '':
LGR.warning(f'The given unit prefix {unit} does not have aliases, '
f'passing it as is')
prefix = orig_unit[:len(unit)]
return prefix + new_unit
else:
return new_unit
LGR.warning(f'The given unit {orig_unit} does not have aliases, '
f'passing it as is')
return orig_unit
3 changes: 3 additions & 0 deletions phys2bids/phys2bids.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
from phys2bids import utils, viz, _version
from phys2bids.cli.run import _get_parser
from phys2bids.physio_obj import BlueprintOutput
from phys2bids.bids_units import bidsify_units

LGR = logging.getLogger(__name__)

Expand Down Expand Up @@ -265,6 +266,8 @@ def phys2bids(filename, info=False, indir='.', outdir='.', heur_file=None,

LGR.info(f'Reading the file {infile}')
phys_in = populate_phys_input(infile, chtrig)
for index, unit in enumerate(phys_in.units):
phys_in.units[index] = bidsify_units(unit)
LGR.info('Reading infos')
phys_in.print_info(filename)
# #!# Here the function viz.plot_channel should be called
Expand Down
14 changes: 14 additions & 0 deletions phys2bids/tests/test_bids_units.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from phys2bids.bids_units import bidsify_units
from phys2bids.bids_units import unit_aliases


def test_bidsify_units():
# test unit with standard prefix
assert bidsify_units('centik') == 'cK'
# test unit with not standard prefix
assert bidsify_units('matV') == 'matV'
# test unit that's not bids standard
assert bidsify_units('mmlie') == 'mmlie'
# test there is not problem with every unit in the dict
for unit_key in unit_aliases.keys():
assert bidsify_units(unit_key) == unit_aliases[unit_key]

0 comments on commit a60e951

Please sign in to comment.