Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BF] fix intendedFor #107

Merged
merged 6 commits into from
Apr 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions dcm2bids/dcm2bids.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ def run(self):
sidecars.append(
Sidecar(filename, self.config.get("compKeys", DEFAULT.compKeys))
)

sidecars = sorted(sidecars)

parser = SidecarPairing(
Expand All @@ -137,15 +138,18 @@ def run(self):
parser.find_runs()

self.logger.info("moving acquisitions into BIDS folder")

intendedForList = [[] for i in range(len(parser.descriptions))]
for acq in parser.acquisitions:
self.move(acq)
intendedForList = self.move(acq, intendedForList)

check_latest()
check_latest("dcm2niix")

def move(self, acquisition):
def move(self, acquisition, intendedForList):
"""Move an acquisition to BIDS format"""
for srcFile in glob(acquisition.srcRoot + ".*"):

_, ext = splitext_(srcFile)
dstFile = os.path.join(self.bidsDir, acquisition.dstRoot + ext)

Expand Down Expand Up @@ -177,18 +181,25 @@ def move(self, acquisition):
pass
defaceTpl = self.config.get("defaceTpl")
cmd = defaceTpl.format(srcFile=srcFile, dstFile=dstFile)

run_shell_command(cmd)
intendedForList[acquisition.indexSidecar].append(acquisition.dstIntendedFor + ext)

# use
elif ext == ".json":
data = acquisition.dstSidecarData(self.config["descriptions"])
data = acquisition.dstSidecarData(self.config["descriptions"],
intendedForList)
save_json(dstFile, data)
os.remove(srcFile)

# just move
else:
os.rename(srcFile, dstFile)

intendedFile = acquisition.dstIntendedFor + ".nii.gz"
if not intendedFile in intendedForList[acquisition.indexSidecar]:
intendedForList[acquisition.indexSidecar].append(intendedFile)

return intendedForList

def get_arguments():
"""Load arguments for main"""
Expand Down
36 changes: 23 additions & 13 deletions dcm2bids/sidecar.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def __init__(self, sidecars, descriptions, searchMethod=DEFAULT.searchMethod,

self._searchMethod = ""
self.graph = OrderedDict()
self.aquisitions = []
self.acquisitions = []

self.sidecars = sidecars
self.descriptions = descriptions
Expand Down Expand Up @@ -154,14 +154,14 @@ def build_graph(self):
A graph (OrderedDict)
"""
graph = OrderedDict((_, []) for _ in self.sidecars)

possibleLinks = itertools.product(self.sidecars, self.descriptions)
for sidecar, description in possibleLinks:
criteria = description.get("criteria", None)
if criteria and self.isLink(sidecar.data, criteria):
graph[sidecar].append(description)
graph[sidecar].append(description)

self.graph = graph

return graph

def isLink(self, data, criteria):
Expand Down Expand Up @@ -213,32 +213,42 @@ def build_acquisitions(self, participant):
A list of acquisition objects
"""
acquisitions = []
acquisitions_intendedFor = []

self.logger.info("Sidecars pairing:")
for sidecar, descriptions in iteritems(self.graph):
for sidecar, valid_descriptions in iteritems(self.graph):
#for sidecar, descriptions in iteritems(self.graph):
sidecarName = os.path.basename(sidecar.root)

# only one description for the sidecar
if len(descriptions) == 1:
desc = descriptions[0]
acq = Acquisition(participant, srcSidecar=sidecar, **desc)
acquisitions.append(acq)
if len(valid_descriptions) == 1:
desc = valid_descriptions[0]
acq = Acquisition(participant,
srcSidecar=sidecar, **desc)
acq.indexSidecar = self.descriptions.index(desc)

if acq.intendedFor != [None]:
acquisitions_intendedFor.append(acq)
else:
acquisitions.append(acq)

self.logger.info("%s <- %s", acq.suffix, sidecarName)

# sidecar with no link
elif len(descriptions) == 0:
elif len(valid_descriptions) == 0:
self.logger.info("No Pairing <- %s", sidecarName)

# sidecar with several links
else:
self.logger.warning("Several Pairing <- %s", sidecarName)
for desc in descriptions:
acq = Acquisition(participant, **desc)
for desc in valid_descriptions:
acq = Acquisition(participant, indexSidecar=self.descriptions.index(desc),
**desc)
self.logger.warning(" -> %s", acq.suffix)

self.acquisitions = acquisitions
return acquisitions
self.acquisitions = acquisitions + acquisitions_intendedFor

return acquisitions + acquisitions_intendedFor

def find_runs(self):
"""
Expand Down
49 changes: 37 additions & 12 deletions dcm2bids/structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ def __init__(
participant,
dataType,
modalityLabel,
indexSidecar=None,
customLabels="",
srcSidecar=None,
sidecarChanges=None,
Expand All @@ -123,16 +124,19 @@ def __init__(
self._modalityLabel = ""
self._customLabels = ""
self._intendedFor = None
self._indexSidecar = None

self.participant = participant
self.dataType = dataType
self.modalityLabel = modalityLabel
self.customLabels = customLabels
self.srcSidecar = srcSidecar

if sidecarChanges is None:
self.sidecarChanges = {}
else:
self.sidecarChanges = sidecarChanges

if intendedFor is None:
self.intendedFor = IntendedFor
else:
Expand Down Expand Up @@ -206,6 +210,18 @@ def dstRoot(self):
self.participant.prefix + self.suffix,
)

@property
def dstIntendedFor(self):
"""
Return:
The destination root inside the BIDS structure for intendedFor
"""
return opj(
self.participant.session,
self.dataType,
self.participant.prefix + self.suffix,
)

@property
def intendedFor(self):
return self._intendedFor
Expand All @@ -217,27 +233,36 @@ def intendedFor(self, value):
else:
self._intendedFor = [value]

def dstSidecarData(self, descriptions):
@property
def indexSidecar(self):
"""
Returns:
A int '_<indexSidecar>'
"""
return self._indexSidecar

@indexSidecar.setter
def indexSidecar(self, value):
"""
Returns:
A int '_<indexSidecar>'
"""
self._indexSidecar = value


def dstSidecarData(self, descriptions, intendedForList):
"""
"""
data = self.srcSidecar.origData
data["Dcm2bidsVersion"] = __version__


# intendedFor key
if self.intendedFor != [None]:
intendedValue = []
for index in self.intendedFor:
intendedDesc = descriptions[index]

session = self.participant.session
dataType = intendedDesc["dataType"]

niiFile = self.participant.prefix
niiFile += self.prepend(intendedDesc.get("customLabels", ""))
niiFile += self.prepend(intendedDesc["modalityLabel"])
niiFile += ".nii.gz"

intendedValue.append(opj(session, dataType, niiFile).replace("\\", "/"))
for index in self.intendedFor:
intendedValue = intendedValue + intendedForList[index]

if len(intendedValue) == 1:
data["IntendedFor"] = intendedValue[0]
Expand Down
2 changes: 1 addition & 1 deletion tests/test_dcm2bids.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def test_dcm2bids():
fmapFile = os.path.join(bidsDir.name, "sub-01", "fmap", "sub-01_echo-492_fmap.json")
data = load_json(fmapFile)
fmapMtime = os.stat(fmapFile).st_mtime
assert data["IntendedFor"] == "dwi/sub-01_dwi.nii.gz"
assert data["IntendedFor"] == os.path.join("dwi", "sub-01_dwi.nii.gz")

data = load_json(
os.path.join(
Expand Down
2 changes: 1 addition & 1 deletion tests/test_structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@
)
def test_acquisition_get_dst_path(name, session, modality, custom, expected):
participant = Participant(name, session)
acquisition = Acquisition(participant, "anat", modality, custom)
acquisition = Acquisition(participant, "anat", modality, customLabels=custom)
assert acquisition.dstRoot == expected