Ejemplo n.º 1
0
    def test_set_anon_rules_invalid(self):
        sorter = DicomSorter()

        with pytest.raises(Exception) as exc_info:
            sorter.set_anonymization_rules('')

        assert exc_info.value.args[0] == 'Anon rules must be a dictionary'
Ejemplo n.º 2
0
    def test_get_available_fields(self, dicom_generator):
        filename, dicom = dicom_generator()
        expected = dicom.dir('')

        root = os.path.dirname(filename)

        sorter = DicomSorter(root)

        assert sorter.available_fields() == expected
Ejemplo n.º 3
0
    def test_set_anon_rules(self):
        sorter = DicomSorter()

        replacements = {
            'Key1': 'Value1',
            'Key2': 'Value2',
        }

        sorter.set_anonymization_rules(replacements)
        assert sorter.anonymization_lookup == replacements
Ejemplo n.º 4
0
    def test_get_available_fields_no_dicoms(self, tmpdir):
        fobj = tmpdir.join('tmp')
        fobj.write('invalid')

        root = str(tmpdir)

        sorter = DicomSorter(root)

        with pytest.raises(DicomFolderError):
            sorter.available_fields()
Ejemplo n.º 5
0
    def test_is_sorting_inactive_sorters(self, mocker):
        sorter = DicomSorter()

        patch = mocker.patch.object(Sorter, 'is_alive')
        patch.return_value = False

        # Generate some sorters
        sorter.sorters.append(default_sorter())
        sorter.sorters.append(default_sorter())

        assert sorter.is_sorting() is False
Ejemplo n.º 6
0
    def test_get_folder_format(self):
        sorter = DicomSorter()
        original = ['1', '2', '3']
        sorter.folders = original

        copy = sorter.folder_format()

        assert copy == original

        # modify the original to ensure it is a different object
        original.append('4')

        assert copy != original
Ejemplo n.º 7
0
    def test_constructor_single_path(self):
        path = '/path'
        sorter = DicomSorter(path)

        assert sorter.pathname == [
            path,
        ]
Ejemplo n.º 8
0
    def test_sort(self, dicom_generator, mocker, tmpdir):
        filename, _ = dicom_generator(SeriesDescription='desc',
                                      SeriesNumber=1,
                                      InstanceNumber=1)

        sorter = DicomSorter()
        sorter.pathname = [
            os.path.dirname(filename),
        ]
        sorter.folders = ['%(SeriesDescription)s']

        output = tmpdir.join('output')

        sorter.sort(str(output))

        # Wait for sorting to complete
        while sorter.is_sorting():
            time.sleep(0.1)

        assert len(sorter.sorters) == 1

        series_folders = output.listdir()
        assert len(series_folders) == 1

        series_folder = series_folders[0]
        assert os.path.basename(str(series_folder)) == 'desc_Series0001'

        images = series_folder.listdir()
        assert len(images) == 1
        assert os.path.basename(str(images[0])) == 'Unknown (0001).dcm'
Ejemplo n.º 9
0
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        self.Create()
        self._InitializeMenus()

        # Use os.getcwd() for now
        self.dicom_sorter = DicomSorter()

        # Store the selected output directory to speed it up
        self.outputDirectory = None

        # Get config from parent
        self.config = configobj.ConfigObj(config.configuration_file)
        # Set interpolation to false since we use formatted strings
        self.config.interpolation = False

        # Check to see if we need to populate the config file
        if len(self.config.keys()) == 0:
            self.config.update(config.default_configuration)
            self.config.write()
        elif 'Version' not in self.config or \
                self.config['Version'] != config.configuration_version:
            self.config.update(config.default_configuration)
            self.config.write()

        self.prefDlg = preferences.PreferenceDlg(self,
                                                 -1,
                                                 '{} Preferences'.format(
                                                     meta.pretty_name),
                                                 config=self.config,
                                                 size=(400, 400))

        self.Bind(wx.EVT_CLOSE, self.OnQuit)

        self.CreateStatusBar()
        self.SetStatusText("Ready...")
Ejemplo n.º 10
0
    def test_constructor_defaults(self):
        sorter = DicomSorter()

        assert sorter.pathname == [
            os.getcwd(),
        ]

        # Booleans
        assert sorter.keep_filename is False
        assert sorter.series_first is False
        assert sorter.keep_original is True

        assert sorter.sorters == []
        assert sorter.folders == []
        assert sorter.anonymization_lookup == dict()
Ejemplo n.º 11
0
class MainFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        self.Create()
        self._InitializeMenus()

        # Use os.getcwd() for now
        self.dicom_sorter = DicomSorter()

        # Store the selected output directory to speed it up
        self.outputDirectory = None

        # Get config from parent
        self.config = configobj.ConfigObj(config.configuration_file)
        # Set interpolation to false since we use formatted strings
        self.config.interpolation = False

        # Check to see if we need to populate the config file
        if len(self.config.keys()) == 0:
            self.config.update(config.default_configuration)
            self.config.write()
        elif 'Version' not in self.config or \
                self.config['Version'] != config.configuration_version:
            self.config.update(config.default_configuration)
            self.config.write()

        self.prefDlg = preferences.PreferenceDlg(self,
                                                 -1,
                                                 '{} Preferences'.format(
                                                     meta.pretty_name),
                                                 config=self.config,
                                                 size=(400, 400))

        self.Bind(wx.EVT_CLOSE, self.OnQuit)

        self.CreateStatusBar()
        self.SetStatusText("Ready...")

    def OnNewVersion(self, evnt):
        dlg = UpdateDlg(self, evnt.version)
        dlg.Show()

    def Create(self):

        # Set Frame icon
        if os.path.isfile(os.path.join(sys.executable, 'DSicon.ico')):
            self.exedir = sys.executable
        else:
            self.exedir = sys.path[0]

        self.SetIcon(icons.main.GetIcon())

        vbox = wx.BoxSizer(wx.VERTICAL)

        self.pathEditor = widgets.PathEditCtrl(self, -1)
        vbox.Add(self.pathEditor, 0, wx.EXPAND)

        titles = ['DICOM Properties', 'Properties to Use']
        self.selector = widgets.FieldSelector(self, titles=titles)

        self.selector.Bind(events.EVT_SORT, self.Sort)

        vbox.Add(self.selector, 1, wx.EXPAND)

        self.SetSizer(vbox)

        self.pathEditor.Bind(events.EVT_PATH, self.FillList)

    def Sort(self, evnt):
        if self.dicom_sorter.is_sorting():
            return

        self.anonymize = evnt.anon

        miscTab = self.prefDlg.pages['Miscpanel']
        self.dicom_sorter.series_first = miscTab.seriesFirst.IsChecked()
        self.dicom_sorter.keep_original = miscTab.keepOriginal.IsChecked()

        if self.anonymize:
            anon_tab = self.prefDlg.pages['Anonymization']
            rules = anon_tab.anonList.GetAnonDict()
            self.dicom_sorter.set_anonymization_rules(rules)
        else:
            self.dicom_sorter.set_anonymization_rules(dict())

        directory_format = evnt.fields

        filename_method = int(self.config['FilenameFormat']['Selection'])
        filename_format = ''

        if filename_method == 0:
            # Image (0001)
            filename_format = DEFAULT_FILENAME
        elif filename_method == 1:
            # Use the original filename
            filename_format = ''
            self.dicom_sorter.keep_filename = True
            # Alternately we could pass None to dicom_sorter
        elif filename_method == 2:
            # Use custom format
            filename_format = self.config['FilenameFormat']['FilenameString']

        self.dicom_sorter.filename = filename_format
        self.dicom_sorter.folders = directory_format

        self.outputDirectory = self.SelectOutputDir()

        if not self.outputDirectory:
            return

        # Use for the real deal
        self.dicom_sorter.sort(self.outputDirectory, listener=self)

        self.Bind(events.EVT_COUNTER, self.OnCount)

    def OnCount(self, event):
        status = '%s / %s' % (event.Count, event.total)
        self.SetStatusText(status)

    def SelectOutputDir(self):
        if not self.outputDirectory:
            # Then don't set a default path
            dlg = wx.DirDialog(self, "Please select an output directory")
        else:
            dlg = wx.DirDialog(self, "Please select an output directory",
                               self.outputDirectory)

        dlg.CenterOnParent()

        if dlg.ShowModal() == wx.ID_OK:
            outputDir = dlg.GetPath()
        else:
            outputDir = None

        dlg.Destroy()

        return outputDir

    def OnPreferences(self, *_event):
        self.config = self.prefDlg.ShowModal()

    def OnQuit(self, *_event):
        sys.exit(0)

    def OnAbout(self, *_event):
        AboutDlg()

    def OnHelp(self, *_event):
        HelpDlg(self)

    def _MenuGenerator(self, parent, name, arguments):
        menu = wx.Menu()

        for item in arguments:
            if item == '----':
                menu.AppendSeparator()
            else:
                menuitem = wx.MenuItem(menu, -1, '\t'.join(item[0:2]))
                if item[2] != '':
                    self.Bind(wx.EVT_MENU, item[2], menuitem)

                menu.Append(menuitem)

        parent.Append(menu, name)

    def LoadDebug(self, *_event):
        size = self.Size
        pos = self.Position

        pos = (pos[0] + size[0], pos[1])

        self.debug = wx.Frame(self,
                              -1,
                              '{} DEBUGGER'.format(meta.pretty_name),
                              size=(700, 500),
                              pos=pos)

        self.crust = wx.py.crust.Crust(self.debug)
        self.debug.Show()

    def QuickRename(self, *_event):
        self.anonList = self.prefDlg.pages['Anonymization'].anonList
        dlg = QuickRenameDlg(self,
                             -1,
                             'Anonymize',
                             size=(250, 160),
                             anonList=self.anonList)
        dlg.ShowModal()

    def _InitializeMenus(self):
        menubar = wx.MenuBar()

        file = [['&Open Directory', 'Ctrl+O',
                 self.pathEditor.BrowsePaths], '----',
                ['&Preferences...', 'Ctrl+,', self.OnPreferences], '----',
                ['&Exit', 'Ctrl+W', self.OnQuit]]

        self._MenuGenerator(menubar, '&File', file)

        win = [['Quick &Rename', 'Ctrl+R', self.QuickRename], '----',
               ['&Debug Window', 'Ctrl+D', self.LoadDebug]]

        self._MenuGenerator(menubar, '&Window', win)

        help = [['About', '', self.OnAbout], ['&Help', 'Ctrl+?', self.OnHelp]]

        self._MenuGenerator(menubar, '&Help', help)

        self.SetMenuBar(menubar)

    def FillList(self, event):
        self.dicom_sorter.pathname = event.path
        try:
            fields = self.dicom_sorter.available_fields()
        except DicomFolderError:
            message = ''.join([';'.join(event.path), ' contains no DICOMs'])
            errors.throw_error(message, 'No DICOMs Present', parent=self)
            return

        self.selector.SetOptions(fields)

        # Now set seriesDescription as the default
        if len(self.selector.selected.Items) == 0:
            self.selector.selected.Append('SeriesDescription')

        # This is clunky
        # TODO: Change PrefDlg to a dict
        self.prefDlg.pages['Anonymization'].SetDicomFields(fields)

        self.Notify(events.PopulateEvent, fields=fields)

    def Notify(self, evntType, **kwargs):
        event = evntType(**kwargs)
        wx.PostEvent(self, event)
Ejemplo n.º 12
0
    def test_get_folder_format_no_folders(self):
        sorter = DicomSorter()
        sorter.folders = None

        assert sorter.folder_format() is None
Ejemplo n.º 13
0
    def test_is_sorting_no_sorters(self):
        sorter = DicomSorter()

        assert sorter.sorters == []
        assert sorter.is_sorting() is False
Ejemplo n.º 14
0
    def test_constructor_multiple_paths(self):
        paths = ['/path1', '/path2']
        sorter = DicomSorter(paths)

        assert sorter.pathname == paths