class AppVariables(object): browse_directory = StringDescriptor( 'browse_directory', default_value=os.path.expanduser('~'), docstring='The directory for browsing for file selection.' ) # type: str remap_type = StringDescriptor('remap_type', default_value='density', docstring='') # type: str image_reader = TypedDescriptor('image_reader', ComplexImageReader, docstring='') # type: ComplexImageReader row_fourier_reader = TypedDescriptor( 'row_fourier_reader', ComplexImageReader, docstring='The row deskewed fourier transformed reader' ) # type: ComplexImageReader row_fourier_file = StringDescriptor( 'row_fourier_file', docstring='The row deskewed fourier transformed reader file' ) # type: str # NB: we are saving this state in order to properly clean up column_fourier_reader = TypedDescriptor( 'column_fourier_reader', ComplexImageReader, docstring='The column deskewed fourier transformed reader' ) # type: ComplexImageReader column_fourier_file = StringDescriptor( 'row_fourier_file', docstring='The column deskewed fourier transformed reader file' ) # type: str # NB: we are saving this state in order to properly clean up derived_row_weights = None # the derived weights for the row scaled_row_mean = None # the scaled mean Fourier transform of the row deskewed data derived_column_weights = None # the derived weights for the column scaled_column_mean = None # the scaled mean Fourier transform of the column deskewed data def __del__(self): # clean up files, because we might need to do so if self.row_fourier_file is not None \ and os.path.exists(self.row_fourier_file): os.remove(self.row_fourier_file) logger.debug('(variables) Removing temp file % s' % self.row_fourier_file) self.row_fourier_file = None if self.column_fourier_file is not None and \ os.path.exists(self.column_fourier_file): os.remove(self.column_fourier_file) logger.debug('(variables) Removing temp file % s' % self.column_fourier_file) self.column_fourier_file = None
class AppVariables(object): browse_directory = StringDescriptor( 'browse_directory', default_value=os.path.expanduser('~'), docstring='The directory for browsing for file selection.') # type: str remap_type = StringDescriptor( 'remap_type', default_value='density', docstring='') # type: str image_reader = TypedDescriptor( 'image_reader', ComplexImageReader, docstring='') # type: ComplexImageReader row_line_low = IntegerDescriptor( 'row_line_low', docstring='The id of the frequency_panel of the lower row bandwidth line.') # type: Union[None, int] row_line_high = IntegerDescriptor( 'row_line_high', docstring='The id of the frequency_panel of the upper row bandwidth line.') # type: Union[None, int] col_line_low = IntegerDescriptor( 'col_line_low', docstring='The id of the frequency_panel of the lower column bandwidth line.') # type: Union[None, int] col_line_high = IntegerDescriptor( 'col_line_high', docstring='The id of the frequency_panel of the upper column bandwidth line.') # type: Union[None, int] row_deltak1 = IntegerDescriptor( 'row_deltak1', docstring='The id of the frequency_panel of the row deltak1 line.') # type: Union[None, int] row_deltak2 = IntegerDescriptor( 'row_deltak2', docstring='The id of the frequency_panel of the row deltak2 line.') # type: Union[None, int] col_deltak1 = IntegerDescriptor( 'col_deltak1', docstring='The id of the frequency_panel of the column deltak1.') # type: Union[None, int] col_deltak2 = IntegerDescriptor( 'col_deltak2', docstring='The id of the frequency_panel of the column deltak2.') # type: Union[None, int]
class AppVariables(object): """ App variables for the aperture tool. """ browse_directory = StringDescriptor( 'browse_directory', default_value=os.path.expanduser('~'), docstring='The directory for browsing for file selection.' ) # type: str image_reader = TypedDescriptor( 'image_reader', STFTCanvasImageReader, docstring='The crsd type canvas image reader object.' ) # type: STFTCanvasImageReader animating = BooleanDescriptor( 'animating', default_value=False, docstring='Are we currently looping through pulses?') # type: bool animation_delay = IntegerDescriptor( 'animation_delay', default_value=30, docstring='Animation delay in milliseconds') # type: int vmin = FloatDescriptor('vmin', default_value=0) # type: float vmax = FloatDescriptor('vmax', default_value=0) # type: float vcount = IntegerDescriptor('vcount', default_value=0) # type: int
class AppVariables(AppVariables_Annotate): file_annotation_collection = TypedDescriptor( 'file_annotation_collection', FileLabelCollection, docstring='The file annotation collection.' ) # type: FileLabelCollection @property def label_schema(self): """ None|LabelSchema: The label schema. """ return None if self.file_annotation_collection is None else \ self.file_annotation_collection.label_schema def get_label(self, label_id): if self.file_annotation_collection is None or label_id is None: return None return self.file_annotation_collection.label_schema.labels[label_id] def get_current_annotation_object(self): """ Gets the current annotation object Returns ------- None|LabelFeature """ if self._current_feature_id is None: return None return self.file_annotation_collection.annotations[ self._current_feature_id]
class AppVariables(object): browse_directory = StringDescriptor( 'browse_directory', default_value=os.path.expanduser('~'), docstring='The directory for browsing for file selection.' ) # type: str image_reader = TypedDescriptor( 'image_reader', SICDTypeCanvasImageReader, docstring='') # type: SICDTypeCanvasImageReader
class AppVariables(object): current_id = StringDescriptor('current_id', default_value=None) # type: Union[None, str] unsaved_edits = BooleanDescriptor('unsaved_edits', default_value=False) # type: bool browse_directory = StringDescriptor( 'browse_directory', default_value=os.path.expanduser('~'), docstring='The directory for browsing for file selection.' ) # type: str label_file_name = StringDescriptor( 'label_file_name', default_value=None) # type: Union[None, str] label_schema = TypedDescriptor('label_schema', LabelSchema) # type: LabelSchema
class AppVariables(AppVariables_Annotate): file_annotation_collection = TypedDescriptor( 'file_annotation_collection', FileRCSCollection, docstring='The file annotation collection.') # type: FileRCSCollection image_reader = TypedDescriptor( 'image_reader', SICDTypeCanvasImageReader, docstring='') # type: SICDTypeCanvasImageReader rcs_viewer_units = StringDescriptor('rcs_viewer_units', default_value='') # type: str def get_current_annotation_object(self): """ Gets the current annotation object Returns ------- None|RCSFeature """ if self._current_feature_id is None: return None return self.file_annotation_collection.annotations[ self._current_feature_id] def get_rcs_units(self): if self.image_reader is None: return [] sicd = self.image_reader.get_sicd() if sicd.Radiometric is None: return ['TotalPixelPower', 'PixelPower'] else: return [ 'TotalRCS', 'PixelPower', 'RCS', 'BetaZero', 'GammaZero', 'SigmaZero' ]
class AppVariables(object): """ The canvas demo app variables. """ browse_directory = StringDescriptor( 'browse_directory', default_value=os.path.expanduser('~')) # type: str selection_rect_id = IntegerDescriptor('selection_rect_id', docstring='') # type: int image_reader = TypedDescriptor('image_reader', ComplexImageReader, docstring='') # type: ComplexImageReader def __init__(self): self.shapes_in_selector = []
class AppVariables(object): browse_directory = StringDescriptor( 'browse_directory', default_value=os.path.expanduser('~'), docstring='The initial opening directory. This will get updated on chosen file.') # type: str image_reader = TypedDescriptor( 'image_reader', ComplexImageReader, docstring='') # type: ComplexImageReader arrow_id = IntegerDescriptor( 'arrow_id', docstring='') # type: int point_id = IntegerDescriptor( 'point_id', docstring='') # type: int horizontal_line_id = IntegerDescriptor( 'horizontal_line_id', docstring='') # type: int line_width = IntegerDescriptor( 'line_width', default_value=3, docstring='') # type: int horizontal_line_width = IntegerDescriptor( 'horizontal_line_width', default_value=3, docstring='') # type: int horizontal_line_color = StringDescriptor( 'horizontal_line_color', default_value='green', docstring='A hexidecimal or named color.') # type: str
class ValidationTool(tkinter.PanedWindow, WidgetWithMetadata): _widget_list = ("button_panel", "text_log_widget") button_panel = TypedDescriptor( 'button_panel', _Buttons, docstring='the button panel') # type: _Buttons text_log_widget = TypedDescriptor( 'text_log_widget', ScrolledText, docstring='the log display') # type: ScrolledText def __init__(self, primary, reader=None, **kwargs): """ Parameters ---------- primary : tkinter.Toplevel|tkinter.Tk reader : None|str|SICDTypeReader|SICDTypeCanvasImageReader """ self.variables = AppVariables() if 'sashrelief' not in kwargs: kwargs['sashrelief'] = tkinter.RIDGE if 'orient' not in kwargs: kwargs['orient'] = tkinter.VERTICAL tkinter.PanedWindow.__init__(self, primary, **kwargs) WidgetWithMetadata.__init__(self, primary) self.pack(expand=tkinter.TRUE, fill=tkinter.BOTH) # handle packing manually self.button_panel = _Buttons(self) self.add(self.button_panel, width=700, height=300, padx=5, pady=5, sticky=tkinter.NSEW) # create the scrolled text widget for logging output self.text_log_widget = ScrolledText(self) # TODO: other configuration? self.add(self.text_log_widget, width=700, height=400, padx=5, pady=5, sticky=tkinter.NSEW) # set the logging handler for the validation logger to log to our widget self.log_handler = TextHandler( self.text_log_widget) # type: TextHandler self.log_handler.setFormatter( logging.Formatter('%(levelname)s:%(asctime)s - %(message)s', '%Y-%m-%dT%H:%M:%S')) # attach this handler to the validation logger self.logger = logging.getLogger('validation') self.logger.setLevel('INFO') self.logger.addHandler(self.log_handler) self.set_title() # define menus self.menu_bar = tkinter.Menu() # file menu self.file_menu = tkinter.Menu(self.menu_bar, tearoff=0) self.file_menu.add_command(label="Open Image", command=self.callback_select_file) self.file_menu.add_command(label="Open Directory", command=self.callback_select_directory) self.file_menu.add_separator() self.file_menu.add_command(label="Save Log", command=self.save_log) self.file_menu.add_command(label="Exit", command=self.exit) # menus for informational popups self.metadata_menu = tkinter.Menu(self.menu_bar, tearoff=0) self.metadata_menu.add_command(label="Metaicon", command=self.metaicon_popup) self.metadata_menu.add_command(label="Metaviewer", command=self.metaviewer_popup) # ensure menus cascade self.menu_bar.add_cascade(label="File", menu=self.file_menu) self.menu_bar.add_cascade(label="Metadata", menu=self.metadata_menu) self.master.config(menu=self.menu_bar) # set the callbacks for the button panel self.button_panel.local_fs_button.config( command=self.callback_local_fs) self.button_panel.full_fs_button.config(command=self.callback_full_fs) self.button_panel.sign_button.config(command=self.callback_sign) self.button_panel.noise_button.config(command=self.callback_noise) self.button_panel.geolocation_button.config( command=self.callback_geolocation) self.update_reader(reader) def _verify_reader(self): # type: () -> bool if self.variables.image_reader is not None: return True showinfo( 'No complex image selected', message='First, select a complex image for this functionality.') return False def _get_and_log_feedback(self, title_text): # type: (str) -> None feedback = FeedbackPopup(self.master, title_text) feedback.root.grab_set() feedback.root.wait_window() if not feedback.use_feedback: return feedback_text = feedback.feedback_text.strip() if feedback_text != '': feedback_text += '\n' if feedback.acceptable: self.logger.info('{} acceptable\n{}'.format( title_text, feedback_text)) else: self.logger.error('{} unacceptable\n{}'.format( title_text, feedback_text)) def set_title(self): """ Sets the window title. """ file_name = None if self.variables.image_reader is None else self.variables.image_reader.file_name if file_name is None: the_title = "Validation Tool" else: the_title = "Image Viewer for {}".format( os.path.split(file_name)[1]) self.winfo_toplevel().title(the_title) def exit(self): self.master.destroy() def save_log(self): if self.variables.image_reader is None or self.log_handler is None: return save_fname = asksaveasfilename( initialdir=self.variables.browse_directory, title="Save validation log output to location?", initialfile='{}.validation.txt'.format( os.path.splitext(self.variables.image_reader.file_name)[0]), filetypes=[ create_filter_entry('Log files', '.log .txt'), all_files ]) if save_fname is None or save_fname in ['', ()]: return if os.path.splitext(save_fname)[1] == '': save_fname += '.validation.txt' self.log_handler.save_to_file(save_fname) def perform_basic_validation(self): if self.variables.image_reader is None: return the_reader = self.variables.image_reader.base_reader if isinstance(the_reader, SICDReader): msg_id = 'SICD structure for file {}'.format(the_reader.file_name) self.logger.info('Starting validation of {}'.format(msg_id)) # noinspection PyUnresolvedReferences result = check_file(the_reader.nitf_details) if result: self.logger.info('***{} appears to be valid***'.format(msg_id)) self.logger.info('Completed validation for {}\n'.format(msg_id)) else: # noinspection PyUnresolvedReferences the_sicds = the_reader.get_sicds_as_tuple() for the_index, the_sicd in enumerate(the_sicds): msg_id = 'SICD structure at index {}'.format( the_index) if len(the_sicds) > 1 else 'SICD structure' self.logger.info('Starting validation of {}'.format(msg_id)) result = the_sicd.is_valid( recursive=True, stack=False) # this implicitly logs things of note if result: self.logger.info( '***{} appears to be valid***'.format(msg_id)) self.logger.info( 'Completed validation for {}\n'.format(msg_id)) def update_reader(self, the_reader, update_browse=None): """ Update the reader. Parameters ---------- the_reader : None|str|SICDTypeReader|SICDTypeCanvasImageReader update_browse : None|str """ if the_reader is None: return if update_browse is not None: self.variables.browse_directory = update_browse elif isinstance(the_reader, str): self.variables.browse_directory = os.path.split(the_reader)[0] if isinstance(the_reader, str): the_reader = SICDTypeCanvasImageReader(the_reader) if isinstance(the_reader, SICDTypeReader): the_reader = SICDTypeCanvasImageReader(the_reader) if not isinstance(the_reader, SICDTypeCanvasImageReader): raise TypeError('Got unexpected input for the reader') # update the reader self.variables.image_reader = the_reader self.set_title() # refresh appropriate GUI elements self.my_populate_metaicon() self.my_populate_metaviewer() self.log_handler.clear() # perform the initial validation self.logger.info('Preparing validation for file {}\n'.format( os.path.abspath(self.variables.image_reader.file_name))) self.perform_basic_validation() def _disconnect_logging(self): if self.log_handler is None: return logger = logging.getLogger('validation') logger.removeHandler(self.log_handler) self.log_handler = None def callback_select_file(self): fname = askopenfilename(initialdir=self.variables.browse_directory, filetypes=common_use_collection) if fname is None or fname in ['', ()]: return try: the_reader = SICDTypeCanvasImageReader(fname) except SarpyIOError: showinfo( 'Opener not found', message='File {} was not successfully opened as a SICD type.'. format(fname)) return self.update_reader(the_reader, update_browse=os.path.split(fname)[0]) def callback_select_directory(self): dirname = askdirectory(initialdir=self.variables.browse_directory, mustexist=True) if dirname is None or dirname in [(), '']: return try: the_reader = SICDTypeCanvasImageReader(dirname) except SarpyIOError: showinfo( 'Opener not found', message= 'Directory {} was not successfully opened as a SICD type.'. format(dirname)) return self.update_reader(the_reader, update_browse=os.path.split(dirname)[0]) def callback_local_fs(self): """ Enable the local frequency support analysis """ if not self._verify_reader(): return # create a complex image reader - don't pass the same one around, so no hidden state reader = SICDTypeCanvasImageReader( self.variables.image_reader.base_reader) # open the frequency support tool based on this reader root = tkinter.Toplevel( self.master ) # create a new toplevel with its own mainloop, so it's blocking tool = LocalFrequencySupportTool(root, reader=reader) root.grab_set() root.wait_window() self._get_and_log_feedback('Local Frequency Support (DeltaKCOAPoly)') def callback_full_fs(self): """ Enable the full image frequency analysis """ if not self._verify_reader(): return # create a complex image reader - don't pass the same one around, so no hidden state reader = SICDTypeCanvasImageReader( self.variables.image_reader.base_reader) # open the frequency support tool based on this reader root = tkinter.Toplevel( self.master ) # create a new toplevel with its own mainloop, so it's blocking tool = FullFrequencySupportTool(root, reader=reader) root.grab_set() root.wait_window() self._get_and_log_feedback('Full Image Frequency Support') def callback_sign(self): """ Enable Fourier sign analysis """ if not self._verify_reader(): return # create a complex image reader - don't pass the same one around, so no hidden state reader = SICDTypeCanvasImageReader( self.variables.image_reader.base_reader) # open the aperture tool based on this reader root = tkinter.Toplevel( self.master ) # create a new toplevel with its own mainloop, so it's blocking tool = RegionSelection(root, reader=reader) root.grab_set() root.wait_window() self._get_and_log_feedback('Fourier Sign') def callback_noise(self): """ Enable noise analysis """ if not self._verify_reader(): return # create a complex image reader - don't pass the same one around, so no hidden state reader = SICDTypeCanvasImageReader( self.variables.image_reader.base_reader) # open the rcs tool based on this reader root = tkinter.Toplevel( ) # create a new toplevel with its own mainloop, so it's blocking tool = RCSTool(root, reader=reader) root.grab_set() root.wait_window() self._get_and_log_feedback('Noise Value') def callback_geolocation(self): """ Enable basic geolocation comparison """ if not self._verify_reader(): return # find a place to save the overlay, then produce it initialdir, fstem = os.path.split( os.path.abspath(self.variables.image_reader.file_name)) dirname = askdirectory(initialdir=initialdir, mustexist=True) if dirname is None or dirname in [(), '']: return fstem_part = os.path.splitext(fstem)[0] kmz_file_stem = 'View-{}'.format(fstem_part) showinfo('KMZ creation', message='This may be somewhat time consuming.\n' 'KMZ file(s) being created in directory {}\n' 'The created filename will begin with {}\n' 'Once the file(s) are created, review and provide feedback.'. format(dirname, kmz_file_stem)) create_kmz_view(self.variables.image_reader.base_reader, dirname, inc_scp=True, inc_collection_wedge=True, file_stem=kmz_file_stem, pixel_limit=3072) showinfo('KMZ creation complete', message='KMZ file(s) created in directory {}\n' 'The created filename(s) begin with {}\n' 'Review and provide feedback.'.format(dirname, kmz_file_stem)) self._get_and_log_feedback('Geolocation') def my_populate_metaicon(self): """ Populate the metaicon. """ self.populate_metaicon(self.variables.image_reader) def my_populate_metaviewer(self): """ Populate the metaviewer. """ self.populate_metaviewer(self.variables.image_reader) def destroy(self): self._disconnect_logging() # noinspection PyBroadException try: super(ValidationTool, self).destroy() except Exception: pass