Пример #1
0
    def set_label_schema(self, label_schema):
        """
        Sets the label schema value.

        Parameters
        ----------
        label_schema : None|str|LabelSchema
        """

        if label_schema is None:
            self.variables.label_file_name = None
            self.variables.label_schema = LabelSchema()
        elif isinstance(label_schema, str):
            the_file = label_schema
            label_schema = LabelSchema.from_file(the_file)
            self.variables.label_file_name = the_file
            self.variables.label_schema = label_schema
            browse_dir = os.path.split(os.path.abspath(the_file))[0]
            self.variables.browse_directory = browse_dir
        elif isinstance(label_schema, LabelSchema):
            self.variables.label_file_name = None
            self.variables.label_schema = label_schema
        else:
            raise TypeError(
                'input must be the path for a label schema file or a LabelSchema instance'
            )

        self.variables.unsaved_edits = False
        self.variables.current_id = None
        self._update_schema_display()
Пример #2
0
    def set_file_name(self, file_name):
        self._file_name = file_name
        if os.path.exists(file_name):
            self.label_schema = LabelSchema.from_file(file_name)
        else:
            self.label_schema = LabelSchema()

        # TODO: set our entries as appropriate
        if self._new_file:
            pass
        else:
            pass
Пример #3
0
def convert_afrl_to_native(research: ResearchType,
                           include_chip: bool = False) -> FileLabelCollection:
    """
    Converts an AFRL structure to a label structure for simple viewing.

    Parameters
    ----------
    research : ResearchType
    include_chip : bool
        Include the chip definition in the geometry structure?

    Returns
    -------
    FileLabelCollection
    """
    def _convert_object_to_json(t_object: TheObjectType) -> LabelFeature:
        # extract the "properties"
        geometry, geometry_properties = t_object.get_image_geometry_object_for_sicd(
            include_chip=include_chip)
        feature = LabelFeature(geometry=geometry,
                               properties=LabelProperties(
                                   name=t_object.SystemName,
                                   geometry_properties=geometry_properties))
        feature.add_annotation_metadata(
            LabelMetadata(label_id=t_object.ObjectLabel))
        return feature

    if not isinstance(research, ResearchType):
        raise TypeError('Expected ResearchType, got type `{}`'.format(
            type(research)))
    if research.DetailObjectInfo is None or \
            research.DetailObjectInfo.Objects is None or \
            len(research.DetailObjectInfo.Objects) == 0:
        raise ValueError('Nothing to be done')

    # create our adhoc containers
    label_schema = LabelSchema(version='AdHoc')
    annotation_collection = LabelCollection()
    for the_object in research.DetailObjectInfo.Objects:
        new_key = the_object.ObjectLabel
        if new_key not in label_schema.labels:
            label_schema.add_entry(new_key, new_key)
        annotation_collection.add_feature(_convert_object_to_json(the_object))

    # finalize the collection
    return FileLabelCollection(
        label_schema,
        annotations=annotation_collection,
        image_file_name=research.DetailImageInfo.DataFilename)
Пример #4
0
    def open_schema(self):
        """
        Open and edit a schema file.

        Returns
        -------
        None
        """

        if self._file_name is not None and self._unsaved_edits:
            result = askyesnocancel(
                title="Unsaved Edits",
                message=
                "There are unsaved edits. Save before opening a new file?")
            if result is True:
                self.save()
            elif result is None:
                return

        schema_file = askopenfilename(
            initialdir=self.browse_directory,
            filetypes=[file_filters.json_files, file_filters.all_files])
        if schema_file == '' or schema_file == ():
            # closed or cancelled
            return

        self.browse_directory = os.path.split(schema_file)[0]
        self._file_name = schema_file

        self._new_file = False
        self._unsaved_edits = False
        self.label_schema = LabelSchema.from_file(schema_file)
        self.schema_viewer.fill_from_label_schema(self.label_schema)
        self._populate_fields_schema()
Пример #5
0
    def new_schema(self):
        """
        Create a new schema.

        Returns
        -------
        None
        """

        schema_file = asksaveasfilename(
            initialdir=self.browse_directory,
            filetypes=[file_filters.json_files, file_filters.all_files])

        if schema_file == '' or schema_file == ():
            # closed or cancelled
            return

        self.browse_directory = os.path.split(schema_file)[0]
        self._file_name = schema_file
        self._new_file = True
        self._unsaved_edits = True
        self.label_schema = LabelSchema()
        self.schema_viewer.fill_from_label_schema(self.label_schema)
        self._populate_fields_schema()
Пример #6
0
    def create_new_annotation_file(self):
        if not self._verify_image_selected():
            return

        # prompt for any unsaved changes
        response = self._prompt_unsaved()
        if not response:
            return

        label_schema_file = self._prompt_for_label_schema()
        if label_schema_file is None:
            label_schema = get_default_schema()
        else:
            label_schema = LabelSchema.from_file(label_schema_file)

        annotations = self._NEW_FILE_ANNOTATION_TYPE(label_schema)
        self.set_annotations(annotations)
Пример #7
0
def _validate_schema(schema):
    """
    Utility function for verifying that an input argument is or points to a LabelSchema.

    Parameters
    ----------
    schema : str|LabelSchema

    Returns
    -------
    LabelSchema
    """

    if isinstance(schema, string_types):
        schema = LabelSchema.from_file(schema)
    if not isinstance(schema, LabelSchema):
        raise TypeError(
            'label_schema must be either a path to am appropriate .json file or a '
            'LabelSchema object. Got type {}'.format(type(schema)))
    return schema
Пример #8
0
    def __init__(self, label_schema, start_item=None):
        """

        Parameters
        ----------
        label_schema : str|LabelSchema
        start_item : None|str
            The initial item selected
        """

        # validate label schema input
        if isinstance(label_schema, str):
            label_schema = LabelSchema.from_file(label_schema)
        if not isinstance(label_schema, LabelSchema):
            raise TypeError(
                'label_schema must be either a path to am appropriate .json file or a '
                'LabelSchema object. Got type {}'.format(type(label_schema)))

        # initialize the selected value option
        self._selected_value = ''

        self.root = tkinter.Toplevel()
        self.root.geometry('250x400')
        self.root.wm_title('Select Label Schema Entry')

        self.viewer = SchemaViewer(self.root, label_schema=label_schema)
        self.viewer.frame.pack(side=tkinter.TOP,
                               expand=tkinter.TRUE,
                               fill=tkinter.BOTH)
        self.set_selected_value(start_item)
        self.submit_button = Button(self.root,
                                    text='Submit',
                                    command=self.set_value)
        self.submit_button.pack(side=tkinter.BOTTOM, expand=tkinter.TRUE)
        self.root.grab_set()
        self.root.wait_window()
Пример #9
0
    def callback_new_schema(self):
        if not self._check_save_state():
            return

        self.set_label_schema(LabelSchema())
Пример #10
0
    def __init__(self, root):
        """

        Parameters
        ----------
        root : tkinter.Toplevel|tkinter.Tk
        """

        self.root = root
        self.browse_directory = os.path.expanduser('~')
        self._file_name = None
        self.label_schema = LabelSchema()  # type: LabelSchema
        self._new_file = None
        self._unsaved_edits = None

        self.primary = basic_widgets.Frame(root)
        WidgetPanel.__init__(self, self.primary)
        self.init_w_rows()
        # self.init_w_basic_widget_list(7, [2, 2, 2, 2, 2, 2, 1])
        # modify packing so that the viewer gets the extra space
        self.version_label.master.pack(expand=tkinter.FALSE, fill=tkinter.X)
        self.version_date_label.master.pack(expand=tkinter.FALSE,
                                            fill=tkinter.X)
        self.classification_label.master.pack(expand=tkinter.FALSE,
                                              fill=tkinter.X)
        self.confidence_label.master.pack(expand=tkinter.FALSE, fill=tkinter.X)
        self.geometries_label.master.pack(expand=tkinter.FALSE, fill=tkinter.X)
        self.edit_button.master.pack(expand=tkinter.FALSE, fill=tkinter.X)
        self.move_up_button.master.pack(expand=tkinter.FALSE, fill=tkinter.X)
        self.schema_viewer.master.pack(expand=tkinter.TRUE,
                                       side=tkinter.BOTTOM)

        # setup the appearance of labels
        self.version_label.config(relief=tkinter.RIDGE,
                                  justify=tkinter.LEFT,
                                  padding=5)
        self.version_date_label.config(relief=tkinter.RIDGE,
                                       justify=tkinter.LEFT,
                                       padding=5)
        self.classification_label.config(relief=tkinter.RIDGE,
                                         justify=tkinter.LEFT,
                                         padding=5)
        self.confidence_label.config(relief=tkinter.RIDGE,
                                     justify=tkinter.LEFT,
                                     padding=5)
        self.geometries_label.config(relief=tkinter.RIDGE,
                                     justify=tkinter.LEFT,
                                     padding=5)

        # setup the GUI callbacks and appearance of labels
        self.version_entry.config(state='disabled',
                                  validate='focusout',
                                  validatecommand=self._version_entry_validate)
        self.version_date_entry.config(state='disabled')
        self.classification_entry.config(
            state='disabled',
            validate='focusout',
            validatecommand=self._classification_validate)
        self.confidence_entry.config(state='disabled',
                                     validate='focusout',
                                     validatecommand=self._confidence_validate)
        self.geometries_entry.config(state='disabled')
        self.edit_button.config(command=self.edit_entry)
        self.new_button.config(command=self.new_entry)
        self.delete_button.config(command=self.delete_entry)
        self.move_up_button.config(command=self.move_up)
        self.move_down_button.config(command=self.move_down)

        # set up the menu bar
        menu = tkinter.Menu()
        filemenu = tkinter.Menu(menu, tearoff=0)
        filemenu.add_command(label="New Schema", command=self.new_schema)
        filemenu.add_command(label="Open Schema", command=self.open_schema)
        filemenu.add_command(label="Save", command=self.save)
        filemenu.add_separator()
        filemenu.add_command(label="Exit", command=self.exit)
        menu.add_cascade(label="File", menu=filemenu)
        self.primary.pack(expand=tkinter.YES, fill=tkinter.BOTH)
        root.config(menu=menu)
Пример #11
0
class SchemaEditor(WidgetPanel):
    _widget_list = (('version_label', 'version_entry'), ('version_date_label',
                                                         'version_date_entry'),
                    ('classification_label', 'classification_entry'),
                    ('confidence_label', 'confidence_entry'),
                    ('geometries_label', 'geometries_entry'),
                    ('new_button', 'edit_button',
                     'delete_button'), ('move_up_button', 'move_down_button'),
                    ('schema_viewer', ))

    version_label = LabelDescriptor(
        'version_label',
        default_text='Version:',
        docstring='The version label')  # type: basic_widgets.Label
    version_entry = EntryDescriptor(
        'version_entry', default_text='',
        docstring='The version value')  # type: basic_widgets.Entry

    version_date_label = LabelDescriptor(
        'version_date_label',
        default_text='Version Date:',
        docstring='The version_date label')  # type: basic_widgets.Label
    version_date_entry = EntryDescriptor(
        'version_date_entry',
        default_text='',
        docstring='The version_date value')  # type: basic_widgets.Entry

    classification_label = LabelDescriptor(
        'classification_label',
        default_text='Classification:',
        docstring='The classification label')  # type: basic_widgets.Label
    classification_entry = EntryDescriptor(
        'classification_entry',
        default_text='',
        docstring='The classification value')  # type: basic_widgets.Entry

    confidence_label = LabelDescriptor(
        'confidence_label',
        default_text='Confidence Values:',
        docstring='The confidence label')  # type: basic_widgets.Label
    confidence_entry = EntryDescriptor(
        'confidence_entry', default_text='',
        docstring='The confidence value')  # type: basic_widgets.Entry

    geometries_label = LabelDescriptor(
        'geometries_label',
        default_text='Geometries:',
        docstring='The geometries label')  # type: basic_widgets.Label
    geometries_entry = EntryDescriptor(
        'geometries_entry', default_text='',
        docstring='The geometries value')  # type: basic_widgets.Entry

    new_button = ButtonDescriptor(
        'new_button',
        default_text='New Entry',
        docstring='The new entry button')  # type: basic_widgets.Button
    edit_button = ButtonDescriptor(
        'edit_button', default_text='Edit Entry',
        docstring='The edit button')  # type: basic_widgets.Button
    delete_button = ButtonDescriptor(
        'delete_button',
        default_text='Delete Entry',
        docstring='The delete entry button')  # type: basic_widgets.Button

    move_up_button = ButtonDescriptor(
        'move_up_button',
        default_text='Move Entry Up',
        docstring='The move up entry button')  # type: basic_widgets.Button
    move_down_button = ButtonDescriptor(
        'move_down_button',
        default_text='Move Entry Down',
        docstring='The move down entry button')  # type: basic_widgets.Button

    schema_viewer = TypedDescriptor(
        'schema_viewer',
        SchemaViewer,
        docstring='The viewer widget for the label schema.'
    )  # type: SchemaViewer

    def __init__(self, root):
        """

        Parameters
        ----------
        root : tkinter.Toplevel|tkinter.Tk
        """

        self.root = root
        self.browse_directory = os.path.expanduser('~')
        self._file_name = None
        self.label_schema = LabelSchema()  # type: LabelSchema
        self._new_file = None
        self._unsaved_edits = None

        self.primary = basic_widgets.Frame(root)
        WidgetPanel.__init__(self, self.primary)
        self.init_w_rows()
        # self.init_w_basic_widget_list(7, [2, 2, 2, 2, 2, 2, 1])
        # modify packing so that the viewer gets the extra space
        self.version_label.master.pack(expand=tkinter.FALSE, fill=tkinter.X)
        self.version_date_label.master.pack(expand=tkinter.FALSE,
                                            fill=tkinter.X)
        self.classification_label.master.pack(expand=tkinter.FALSE,
                                              fill=tkinter.X)
        self.confidence_label.master.pack(expand=tkinter.FALSE, fill=tkinter.X)
        self.geometries_label.master.pack(expand=tkinter.FALSE, fill=tkinter.X)
        self.edit_button.master.pack(expand=tkinter.FALSE, fill=tkinter.X)
        self.move_up_button.master.pack(expand=tkinter.FALSE, fill=tkinter.X)
        self.schema_viewer.master.pack(expand=tkinter.TRUE,
                                       side=tkinter.BOTTOM)

        # setup the appearance of labels
        self.version_label.config(relief=tkinter.RIDGE,
                                  justify=tkinter.LEFT,
                                  padding=5)
        self.version_date_label.config(relief=tkinter.RIDGE,
                                       justify=tkinter.LEFT,
                                       padding=5)
        self.classification_label.config(relief=tkinter.RIDGE,
                                         justify=tkinter.LEFT,
                                         padding=5)
        self.confidence_label.config(relief=tkinter.RIDGE,
                                     justify=tkinter.LEFT,
                                     padding=5)
        self.geometries_label.config(relief=tkinter.RIDGE,
                                     justify=tkinter.LEFT,
                                     padding=5)

        # setup the GUI callbacks and appearance of labels
        self.version_entry.config(state='disabled',
                                  validate='focusout',
                                  validatecommand=self._version_entry_validate)
        self.version_date_entry.config(state='disabled')
        self.classification_entry.config(
            state='disabled',
            validate='focusout',
            validatecommand=self._classification_validate)
        self.confidence_entry.config(state='disabled',
                                     validate='focusout',
                                     validatecommand=self._confidence_validate)
        self.geometries_entry.config(state='disabled')
        self.edit_button.config(command=self.edit_entry)
        self.new_button.config(command=self.new_entry)
        self.delete_button.config(command=self.delete_entry)
        self.move_up_button.config(command=self.move_up)
        self.move_down_button.config(command=self.move_down)

        # set up the menu bar
        menu = tkinter.Menu()
        filemenu = tkinter.Menu(menu, tearoff=0)
        filemenu.add_command(label="New Schema", command=self.new_schema)
        filemenu.add_command(label="Open Schema", command=self.open_schema)
        filemenu.add_command(label="Save", command=self.save)
        filemenu.add_separator()
        filemenu.add_command(label="Exit", command=self.exit)
        menu.add_cascade(label="File", menu=filemenu)
        self.primary.pack(expand=tkinter.YES, fill=tkinter.BOTH)
        root.config(menu=menu)

    def set_file_name(self, file_name):
        self._file_name = file_name
        if os.path.exists(file_name):
            self.label_schema = LabelSchema.from_file(file_name)
        else:
            self.label_schema = LabelSchema()

        # TODO: set our entries as appropriate
        if self._new_file:
            pass
        else:
            pass

    # main schema element edit callbacks - piggyback on validation methods
    def _version_entry_validate(self):
        the_value = self.version_entry.get().strip()
        if the_value != '' and self.label_schema.version != the_value:
            self._unsaved_edits = True
            self.label_schema._version = the_value
            self.label_schema.update_version_date(value=None)
            self.version_date_entry.set_text(self.label_schema.version_date)
        return True

    def _classification_validate(self):
        the_value = self.classification_entry.get().strip()
        if self.label_schema.classification != the_value:
            self._unsaved_edits = True
            self.label_schema._classification = the_value
        return True

    def _confidence_validate(self):
        the_value = self.confidence_entry.get().strip()
        print('the confidence value', the_value)
        if the_value == '':
            the_values = None
        else:
            temp_values = the_value.split()

            # noinspection PyBroadException
            try:
                the_values = [int(entry) for entry in temp_values]
            except:
                the_values = temp_values

        if self.label_schema.confidence_values != the_values:
            self._unsaved_edits = True
            self.label_schema.confidence_values = the_values
        return True

    def _populate_fields_schema(self):
        """
        Populate the GUI values from the schema.

        Returns
        -------
        None
        """

        self.version_entry.config(state='normal')
        self.version_entry.set_text(self.label_schema.version)

        self.version_date_entry.set_text(self.label_schema.version_date)

        self.classification_entry.config(state='normal')
        self.classification_entry.set_text(self.label_schema.classification)

        self.confidence_entry.config(state='normal')
        if self.label_schema.confidence_values is None:
            self.confidence_entry.set_text('')
        else:
            self.confidence_entry.set_text(' '.join(
                '{}'.format(entry)
                for entry in self.label_schema.confidence_values))

        self.confidence_entry.config(state='normal')
        if self.label_schema.permitted_geometries is None:
            self.geometries_entry.set_text('')
        else:
            self.geometries_entry.set_text(' '.join(
                self.label_schema.permitted_geometries))

    def edit_entry(self):
        """
        Edit the selected element.

        Returns
        -------
        None
        """

        if self._file_name is None:
            showinfo('No Schema Selected',
                     message='Choose schema location from File menu')
            return

        selected = self.schema_viewer.treeview.focus()
        if selected == '':
            showinfo('No Element Selected',
                     message='Choose element from Viewer')
            return

        popup = LabelEntryWidget(self.label_schema, edit_id=selected)
        if popup.id_changed is not None:
            self.schema_viewer.rerender_entry(popup.id_changed)
            self._unsaved_edits = True
        popup.destroy()

    def new_entry(self):
        """
        Create a new label schema entry.

        Returns
        -------
        None
        """

        if self._file_name is None:
            showinfo('No Schema Selected',
                     message='Choose schema location from File menu')
            return

        popup = LabelEntryWidget(self.label_schema, edit_id=None)
        if popup.id_changed is not None:
            self.schema_viewer.rerender_entry(popup.id_changed)
            self._unsaved_edits = True
        popup.destroy()

    def delete_entry(self):
        """
        Delete the selected entry.

        Returns
        -------
        None
        """
        if self._file_name is None:
            showinfo('No Schema Selected',
                     message='Choose schema location from File menu')
            return

        selected = self.schema_viewer.treeview.focus()
        if selected == '':
            showinfo('No Element Selected',
                     message='Choose element from Viewer')
            return

        # does the selected entry have any children?
        children = self.label_schema.subtypes.get(selected, None)
        if children is not None and len(children) > 0:
            response = askyesnocancel(
                'Delete Children?',
                message='Selected entry has children. Delete all children?')
            if response is not True:
                return
        self.schema_viewer.delete_entry(selected)
        self._unsaved_edits = True

    def move_up(self):
        """
        Move the selected entry up one spot.

        Returns
        -------
        None
        """

        if self._file_name is None:
            showinfo('No Schema Selected',
                     message='Choose schema location from File menu')
            return

        selected = self.schema_viewer.treeview.focus()
        if selected == '':
            showinfo('No Element Selected',
                     message='Choose element from Viewer')
            return

        result = self.label_schema.reorder_child_element(selected, spaces=-1)
        if result:
            self.schema_viewer.rerender_entry(selected)
            self._unsaved_edits = True

    def move_down(self):
        """
        Move the selected entry down one spot.

        Returns
        -------
        None
        """

        if self._file_name is None:
            showinfo('No Schema Selected',
                     message='Choose schema location from File menu')
            return

        selected = self.schema_viewer.treeview.focus()
        if selected == '':
            showinfo('No Element Selected',
                     message='Choose element from Viewer')
            return

        result = self.label_schema.reorder_child_element(selected, spaces=1)
        if result:
            self.schema_viewer.rerender_entry(selected)
            self._unsaved_edits = True

    def new_schema(self):
        """
        Create a new schema.

        Returns
        -------
        None
        """

        schema_file = asksaveasfilename(
            initialdir=self.browse_directory,
            filetypes=[file_filters.json_files, file_filters.all_files])

        if schema_file == '' or schema_file == ():
            # closed or cancelled
            return

        self.browse_directory = os.path.split(schema_file)[0]
        self._file_name = schema_file
        self._new_file = True
        self._unsaved_edits = True
        self.label_schema = LabelSchema()
        self.schema_viewer.fill_from_label_schema(self.label_schema)
        self._populate_fields_schema()

    def open_schema(self):
        """
        Open and edit a schema file.

        Returns
        -------
        None
        """

        if self._file_name is not None and self._unsaved_edits:
            result = askyesnocancel(
                title="Unsaved Edits",
                message=
                "There are unsaved edits. Save before opening a new file?")
            if result is True:
                self.save()
            elif result is None:
                return

        schema_file = askopenfilename(
            initialdir=self.browse_directory,
            filetypes=[file_filters.json_files, file_filters.all_files])
        if schema_file == '' or schema_file == ():
            # closed or cancelled
            return

        self.browse_directory = os.path.split(schema_file)[0]
        self._file_name = schema_file

        self._new_file = False
        self._unsaved_edits = False
        self.label_schema = LabelSchema.from_file(schema_file)
        self.schema_viewer.fill_from_label_schema(self.label_schema)
        self._populate_fields_schema()

    def save(self):
        """
        Save any current progress.

        Returns
        -------
        None
        """

        if self._file_name is None:
            showinfo('No Schema Selected',
                     message='Choose schema location from File menu')
            return

        if self._unsaved_edits:
            self.label_schema.to_file(self._file_name)
            self._unsaved_edits = False

    def exit(self):
        """
        Exit the application.

        Returns
        -------
        None
        """

        if self._file_name is not None and self._unsaved_edits:
            save_state = askyesno('Save Progress',
                                  message='There are unsaved edits. Save?')
            if save_state is True:
                self.save()
        self.root.destroy()
Пример #12
0
def get_default_schema():
    return LabelSchema(labels={'0': 'unknown'})