hurahura package

Subpackages

Submodules

hurahura.mi_config module

hurahura.mi_subject module

Created on Thu Apr 26 10:59:36 2018

@author: Fraser M Callaghan

Classes for building standardised imaging projects. Adapted for general use from KMR project.

class hurahura.mi_subject.AbstractSubject(subjectNumber, dataRoot, subjectPrefix=None, padZeros=None, suffix='')[source]

Bases: object

An abstract subject controlling most basic structure

addOtherData(directoryToLoad)[source]
anonymise(anonName=None, anonID='', QUIET=False)[source]

Check if anonName is valid and return anonName and anonID If anonName = SOFT then set an encoded name in meta file and retain PatientID - anonymise DICOMS If anonName = HARD then set encoded name in meta file to “Unknown” - anonymise DICOMS If anonName is None then anonymise DICOMS Else anonymise DICOMS with anonName for Name and PatientID

archiveSubject(archiveRoot)[source]

Move a subject to another dataRoot then delete local files (keep META and directory structure). Use case to build and run pipelines on high performance local ssd then to move subject to e.g. NAS - still available for future interrogation.

NOTE: This relies on rsync for the transfer on linux / mac. Falls back to shutil opn Windows.

Parameters:

archiveRoot (str) – directory path to the new dataRoot

Returns:

0 for success else 1.

Return type:

int

buildDicomMeta()[source]

Builds a JSON file comprised of DICOM tags and some derived values. All data is taken from DICOM files - StudyDate, PatientID, MagneticFieldStrength etc A ‘Series’ tag is populated with a list of all series with series information (same as found in ScanSeriesInfo.csv)

NOTE: miresearch expects one study (scanner exam instance) per subjectID. There are occasions where multiple studies occur but should be treated as one study. E.g.: the subject got off the table and then resummed the study later. miresearch will account for this by recording tags from the first found ‘study’ at the study level and from ALL found series to populate the list of series.

buildSeriesDataMetaCSV(FORCE=False)[source]
countNumberOfDicoms()[source]
delteAllButMeta()[source]

Delete all contents of subject except META data (leave directory srtructure). Often after “archiveSubject”

Returns:

0 for success else 1

Return type:

int

exists()[source]
findDicomSeries(seriesDescription)[source]
getAge()[source]

This returns a float, and is slightly wrong in account of leap years. This is intentional. :return: years - float

getDicomFile(seriesNum, instanceNum=1)[source]
getDicomFoldersListStr(FULL=True, excludeSeNums=None)[source]
getDicomSeriesDir(seriesNum, seriesUID=None)[source]
getDicomSeriesDir_Description(seriesDescription)[source]
getDicomSeriesMeta(seriesNumber=None, seriesDescription=None)[source]
getDicomSeriesMetaList()[source]
getDicomSeriesNumber_Interactive()[source]
getDicomsDir()[source]
getDifferenceBetweenStartTimesOfTwoScans_s(seN1, seN2)[source]
getGender()[source]
getHRForSeriesN(N, df=None)[source]
getInfoStr(extraKeys=[])[source]
getLevelCompleted()[source]
getListOfSeNums()[source]
getMetaDict(suffix='')[source]

Get meta json file as dictionary

Parameters:

suffix (str, optional) – Suffix of json file. Defaults to “”.

Returns:

Meta json file

Return type:

dict

getMetaDir()[source]
getMetaTagValue(tag, NOT_FOUND=None, metaSuffix='')[source]

Get specific tag from meta json file

Parameters:
  • tag (str) – Name of tag to return

  • NOT_FOUND (ANY, optional) – A default value to return if “tag” not found. Defaults to None.

  • metaSuffix (str, optional) – Suffix of json file. Defaults to “”.

Raises:

e – OSError if meta json file not found

Returns:

tag value from json file

Return type:

ANY

getMetaTagsFile(suffix='')[source]
getName()[source]
getName_FirstNames()[source]
getPrefix_Number()[source]
getRawDir()[source]
getRawDirOther(BUILD_IF_NEED=True)[source]
getSeriesDescriptionsStr()[source]
getSeriesMetaAsDataFrame()[source]
getSeriesMetaCSV()[source]
getSeriesMetaValue(seNum, varName)[source]

Get meta value for given series naumber

Parameters:
  • seNum (int) – series number

  • varName (str) – tag name, from: EchoTime FlipAngle HeartRate InPlanePhaseEncodingDirection InternalPulseSequenceName PulseSequenceName RepetitionTime ScanDuration SeriesDescription SeriesNumber SpacingBetweenSlices StartTime dCol dRow dSlice dTime nCols nRow nSlice nTime

Returns:

tag value

Return type:

ANY

getSeriesNumbersMatchingDescriptionStr(descriptionStr)[source]
getSpydcmDicomSeries(seNumber)[source]
getSpydcmDicomStudy()[source]
getStartTimeForSeriesN_HHMMSS(N, df=None)[source]
getStartTime_EndTimeOfExam()[source]
getStudyDate(RETURN_Datetime=False)[source]
getStudyID()[source]
getSummary_list()[source]
getTagValue(tagName, ifNotFound='Unknown', metaSuffix='')[source]
getTimeTakenForSeriesN_s(N, df=None)[source]
getTopDir()[source]
getTotalScanTime_s()[source]
classmethod get_ui_methods()[source]

Get all methods marked with @ui_method decorator, including inherited ones

hasDicomSeries(seriesDescription)[source]
info()[source]
infoFull()[source]
initDirectoryStructure()[source]
isAnonymised()[source]
isMale()[source]
loadDicomsToSubject(dicomFolderToLoad, anonName=None, HIDE_PROGRESSBAR=False)[source]
loadSpydcmStudyToSubject(spydcmData, anonName=None)[source]
property logfileName
property logger
printDicomsInfo()[source]
renameSubjID(newSubjID)[source]
rsyncToOtherDataroot(otherDataRoot)[source]
runPostLoadPipeLine(*args, **kwargs)[source]
setEncodedName(NAME, FIRST_NAMES='')[source]
setIsAnonymised()[source]
setLoggerDebug()[source]
setLoggerInfo()[source]
setTagValue(tag, value, suffix='')[source]
property subjID
property subjN
updateMetaFile(metaDict, metasuffix='')[source]

Update the meta json file

Parameters:
  • metaDict (dict) – dictionary with key value pairs to update

  • metasuffix (str, optional) – Suffix of json file. Defaults to “”.

zipUpSubject(outputDirectory, fileName=None, EXCLUDE_RAW=False)[source]

Will zip a subject and place in given output directory

Parameters:
  • outputDirectory (str) – path to output directory

  • fileName (str, optional) – If given then this is zip filename, if not given then use subjID. Defaults to None.

  • EXCLUDE_RAW (bool, optional) – Set true to exclude RAW data - helpful for sharing. Defaults to False.

Returns:

the results full archive name

Return type:

str

class hurahura.mi_subject.SubjectList(subjList=[])[source]

Bases: list

Container for a list of subjects

filterSubjectListByDOS(dateOfScan_YYYYMMDD, dateEnd_YYYYMMDD=None)[source]

Take list, return only those that match DOS or between start and end (inclusive) if dateEnd given :param subjList: :param dateOfScan_YYYYMMDD: str :param dateEnd_YYYYMMDD: str - optional :return:

filterSubjectListByDOS_closest(dateOfScan_YYYY_MM_DD, A_less_than_B=False)[source]

Reduce sList to one - closest to dateOfScan

Keyword arguments: subjList – list of KMR_CARDIAC objects dateOfScan_YYYY_MM_DD – date of scan string to query A_less_than_B = check to force subjDateOfScan <= dateOfScan query Return: subjList length one

findSubjMatchingName(nameStr, dateOfScan_YYYYMMDD=None, decodePassword=None)[source]
Parameters:
  • nameStr

  • dateOfScan_YYYYMMDD – if given will use to filter list matching name

Returns:

SubjectList

findSubjMatchingPatientID(patientID, dateOfScan_YYYYMMDD=None, tolerance_days=0)[source]
Parameters:
  • patientID

  • dateOfScan_YYYY_MM_DD – list of ints for DOS to fix ambiguity

Returns:

SubjectList

findSubjMatchingStudyID(studyID)[source]
Parameters:

examID) (studyID (or) – int

Returns:

mi_subject

findSubjMatchingStudyUID(studyUID)[source]
findSubjMatching_SubjN(subjN)[source]
Parameters:

examID) (studyID (or) – int

Returns:

mi_subject

reduceToExist()[source]
reduceToSet()[source]
classmethod setByDirectory(dataRoot, subjectPrefix=None, SubjClass=<class 'hurahura.mi_subject.AbstractSubject'>)[source]
property subjIDs
property subjNs
writeSummaryCSV(outputFileName_csv, extra_series_tags=[])[source]
hurahura.mi_subject.WriteSubjectStudySummary(dataRootDir, summaryFilePath=None, subjPrefix=None, SubjClass=<class 'hurahura.mi_subject.AbstractSubject'>)[source]
hurahura.mi_subject.buildSubjectID(subjN, subjectPrefix, padZeros=None, suffix='')[source]
hurahura.mi_subject.createNew_OrAddTo_Subject(loadDirectory, dataRoot, SubjClass=<class 'hurahura.mi_subject.AbstractSubject'>, subjNumber=None, subjPrefix=None, anonName=None, LOAD_MULTI=False, IGNORE_UIDS=False, QUIET=False, OTHER_DATA_DIR=None)[source]

Used to create a new subject (or add data to already existing subject) from an input directory (or compressed file). Current compressed file tpyes supported: zip, tar, tar.gz

Parameters:
  • loadDirectory (str) – the directory from which data to be loaded

  • dataRoot (str) – the root directory where subjects are stored

  • SubjClass (subclass of AbstractClass, optional) – subclass of AbstractClass. Defaults to AbstractSubject.

  • subjNumber (int, optional) – subject number to create or load to. Will take next available number if none given. Defaults to None.

  • subjPrefix (str, optional) – the subject prefix. If not given will attempt to guess from dataRoot. Defaults to None.

  • anonName (str, optional) – An anonymis name to give to this subject. Defaults to None.

  • LOAD_MULTI (bool, optional) – If true then each sub-directory in “loadDirectory” will be used to load a new subject. Defaults to False.

  • IGNORE_UIDS (bool, optional) – If true then ignore dicom UIDs and each sub-directory in “loadDirectory” will DEFINITLY be a new subject. Defaults to False.

  • QUIET (bool, optional) – If true will supress output. Defaults to False.

  • OTHER_DATA_DIR (str, optional) – If given then add other data (non-dicoms) from this directory to the subject. Defaults to None.

Raises:

ValueError – If incompatible arguments given (can not give subjNumber if LOAD_MULTI is given)

Returns:

list of Subject Objects added to or created

Return type:

list

hurahura.mi_subject.doDatesMatch(dateA, dateB, tolerance_days=1)[source]
hurahura.mi_subject.doesSubjectExist(subjN, dataRootDir, subjectPrefix=None, padZeros=None, suffix='')[source]
hurahura.mi_subject.findSubjMatchingDicomStudyUID(dicomDir_OrData, dataRoot, subjPrefix=None, SubjClass=<class 'hurahura.mi_subject.AbstractSubject'>)[source]
hurahura.mi_subject.findZeroPadding(subjID)[source]
hurahura.mi_subject.getAllSubjects(dataRootDir, subjectPrefix=None, SubjClass=<class 'hurahura.mi_subject.AbstractSubject'>)[source]
hurahura.mi_subject.getAllSubjectsN(dataRootDir, subjectPrefix=None)[source]
hurahura.mi_subject.getNextSubjID(dataRootDir, subjectPrefix=None)[source]
hurahura.mi_subject.getNextSubjN(dataRootDir, subjectPrefix=None)[source]
hurahura.mi_subject.getNumberFromSubjID(subjID)[source]
hurahura.mi_subject.getSubjects(subjectNList, dataRootDir, subjectPrefix=None, SubjClass=<class 'hurahura.mi_subject.AbstractSubject'>)[source]
hurahura.mi_subject.guessSubjectPrefix(dataRootDir, QUIET=False)[source]

Guess the subject prefix by looking for common names in the dataRootDir

Parameters:
  • dataRootDir (str) – path to root directory of subject filesystem database

  • QUIET (bool) – Set True to suppress output (default False)

Returns:

subject prefix string

Return type:

str

Exception:

mi_utils.SubjPrefixError: is ambiguous

hurahura.mi_subject.splitSubjID(s)[source]

Strip a subject ID to prefix and number

Parameters:

s (str) – subject ID

Returns:

prefix: str, number: int (if len 3 - then also suffix: str)

Return type:

tuple

hurahura.mi_subject.subjNListToSubjObj(subjNList, dataRoot, subjPrefix, SubjClass=<class 'hurahura.mi_subject.AbstractSubject'>, CHECK_EXIST=True)[source]
hurahura.mi_subject.ui_method(description='', category='General', order=100)[source]

Decorator to mark methods that should be available in UI

Parameters:
  • description (str) – Description of what the method does

  • category (str) – Category for grouping in UI

  • order (int) – Display order in UI (lower numbers first)

hurahura.mi_utils module

class hurahura.mi_utils.DirectoryStructure(name, childrenList=[])[source]

Bases: object

class hurahura.mi_utils.DirectoryStructureTree[source]

Bases: list

addNewStructure(name_or_list)[source]
isSecondLevelName(nameTop, nameSecond)[source]
isTopLevelName(name)[source]
exception hurahura.mi_utils.SubjPrefixError(msg2='')[source]

Bases: Exception

If errors to do with the subject prefix

hurahura.mi_utils.buildDirectoryStructureTree(listOfExtraSubfolders=[])[source]
This will build the directory structure for a project using the structure

found in config file and any added subfolder names

Parameters:

listOfExtraSubfolders (list) –

A list of subfolders, if an entry is itself a list, then the first item of that entry is the toplevel subfolder and the following items are subfolders of that toplevel folder. Default: empty list Note: A default structure is always used of: | - META | - RAW

- DICOM

hurahura.mi_utils.countFilesInDir(dirName)[source]
hurahura.mi_utils.datetimeToStrTime(dateTimeVal, strFormat='%H%M%S')[source]
hurahura.mi_utils.decodeString(encStr, passcode)[source]
hurahura.mi_utils.encodeString(strIn, passcode)[source]
hurahura.mi_utils.getDataRootDir()[source]
hurahura.mi_utils.readFileToListOfLines(fileName, commentSymbol='#')[source]

Read file - return list - elements made up of each line Will split on “,” if present Will skip starting with #

hurahura.mi_utils.subjFileToSubjN(subjFile)[source]
hurahura.mi_utils.timeToDatetime(timeStr)[source]
hurahura.mi_utils.writeCSVFile(data, header, csvFile, FIX_NAN=False)[source]

hurahura.miresearch_main module

Module that exposes the routines and utilities making up MIRESEARCH

class hurahura.miresearch_main.MiResearchParser(prog=None, usage=None, description=None, epilog=None, parents=[], formatter_class=<class 'argparse.HelpFormatter'>, prefix_chars='-', fromfile_prefix_chars=None, argument_default=None, conflict_handler='error', add_help=True, allow_abbrev=True, exit_on_error=True)[source]

Bases: ArgumentParser

error(message: string)[source]

Prints a usage message incorporating the message to stderr and exits.

If you override this in a subclass, it should not return – it should either exit or raise an exception.

hurahura.miresearch_main.checkArgs(args, class_obj=None)[source]
hurahura.miresearch_main.main(extra_runActions=None, class_obj=None)[source]
hurahura.miresearch_main.runActions(args, extra_runActions=None)[source]
hurahura.miresearch_main.setNList(args)[source]

hurahura.miresearch_watchdog module

exception hurahura.miresearch_watchdog.MIResearchWatchDogError(message='An error occurred')[source]

Bases: Exception

A custom error class.

class hurahura.miresearch_watchdog.MIResearch_SubdirectoryHandler(directoryToWatch, dataStorageRoot, subjectPrefix, logger, SubjClass=<class 'hurahura.mi_subject.AbstractSubject'>, TO_ANONYMISE=False, DEBUG=False)[source]

Bases: FileSystemEventHandler

execute_loadDirectory(directoryToLoad)[source]
findMatchingProcessingDirs(src_path)[source]
is_stable(directory_path)[source]

Check if this new directory is stable (no change in modified time)

Parameters:

directory_path (str) – the directory to check for stability

Returns:

True if stable AND not already being processed.

Return type:

bool

matches_ignore_pattern(subdirectory)[source]
on_created(event)[source]

Called when a file or directory is created.

Parameters:

event (DirCreatedEvent or FileCreatedEvent) – Event representing file/directory creation.

on_deleted(event)[source]

Called when a file or directory is deleted.

Parameters:

event (DirDeletedEvent or FileDeletedEvent) – Event representing file/directory deletion.

on_moved(event)[source]

Called when a file or a directory is moved or renamed.

Parameters:

event (DirMovedEvent or FileMovedEvent) – Event representing file/directory movement.

class hurahura.miresearch_watchdog.MIResearch_WatchDog(directoryToWatch, dataStorageRoot, subjectPrefix, SubjClass=<class 'hurahura.mi_subject.AbstractSubject'>, TO_ANONYMISE=False, DEBUG=False)[source]

Bases: object

A watchdog for MI Research built off watchdog Will watch a directory and load new subjects as they arrive

run()[source]
hurahura.miresearch_watchdog.getLogger(id, logfileName, DEBUG=False)[source]
hurahura.miresearch_watchdog.get_directory_modified_time(directory_path)[source]

Module contents