def __init__( self, features: FeatureExtractor, young_laplace_fit: YoungLaplaceFitter, params: PhysicalPropertiesCalculatorParams, ) -> None: self._extracted_features = features self._young_laplace_fit = young_laplace_fit self.params = params self.bn_interfacial_tension = BoxBindable(math.nan) self.bn_volume = BoxBindable(math.nan) self.bn_surface_area = BoxBindable(math.nan) self.bn_apex_radius = BoxBindable(math.nan) self.bn_worthington = BoxBindable(math.nan) features.bn_needle_width_px.on_changed.connect(self._recalculate) # Assume that bond number changes at the same time as other attributes young_laplace_fit.bn_bond_number.on_changed.connect(self._recalculate) params.bn_inner_density.on_changed.connect(self._recalculate) params.bn_outer_density.on_changed.connect(self._recalculate) params.bn_needle_width.on_changed.connect(self._recalculate) params.bn_gravity.on_changed.connect(self._recalculate) self._recalculate()
def __init__(self, should_save: bool, dpi: int, size_w: float, size_h: float) -> None: self.bn_should_save = BoxBindable(should_save) self.bn_dpi = BoxBindable(dpi) self.bn_size_w = BoxBindable(size_w) self.bn_size_h = BoxBindable(size_h) # Validation self.dpi_err = validate( value=self.bn_dpi, checks=(check_is_not_empty, check_is_positive), enabled=self.bn_should_save) self.size_w_err = validate( value=self.bn_size_w, checks=(check_is_not_empty, check_is_positive), enabled=self.bn_should_save) self.size_h_err = validate( value=self.bn_size_h, checks=(check_is_not_empty, check_is_positive), enabled=self.bn_should_save) self.errors = bn_apply(lambda *args: any(args), self.dpi_err, self.size_w_err, self.size_h_err)
def _do_init(self, model: ConanResultsModel, page_controls: WizardPageControls) -> None: self._loop = asyncio.get_event_loop() self._model = model self._page_controls = page_controls self.individual_model = model.individual self.graphs_model = model.graphs self.bn_footer_status = BoxBindable(ResultsFooterStatus.IN_PROGRESS) self.bn_completion_progress = model.bn_analyses_completion_progress self.bn_time_elapsed = BoxBindable(math.nan) self.bn_time_remaining = BoxBindable(math.nan) self._active_save_options = None self.__event_connections = [ model.bn_analyses_time_start.on_changed.connect( self._update_times), model.bn_analyses_time_est_complete.on_changed.connect( self._update_times), ] self._update_times()
def __init__(self) -> None: self.bn_save_dir_parent = BoxBindable(None) # type: Bindable[Optional[Path]] self.bn_save_dir_name = BoxBindable('') self.drop_residuals_figure_opts = FigureOptions( should_save=True, dpi=300, size_w=10, size_h=10 ) self.ift_figure_opts = FigureOptions( should_save=True, dpi=300, size_w=15, size_h=9 ) self.volume_figure_opts = FigureOptions( should_save=True, dpi=300, size_w=15, size_h=9 ) self.surface_area_figure_opts = FigureOptions( should_save=True, dpi=300, size_w=15, size_h=9 )
def __init__( self, *, image_acquisition: ImageAcquisitionModel, feature_extractor_params: FeatureExtractorParams, do_extract_features: Callable[[Bindable[np.ndarray]], FeatureExtractor] ) -> None: self._image_acquisition = image_acquisition self._feature_extractor_params = feature_extractor_params self._do_extract_features = do_extract_features self._watchers = 0 self._acquirer_controller = None # type: Optional[AcquirerController] self.bn_acquirer_controller = AccessorBindable( getter=lambda: self._acquirer_controller) self.bn_source_image = BoxBindable( None) # type: Bindable[Optional[np.ndarray]] self.bn_foreground_detection = BoxBindable( None) # type: Bindable[Optional[np.ndarray]] self.bn_drop_profile = BoxBindable( None) # type: Bindable[Optional[np.ndarray]] self._image_acquisition.bn_acquirer.on_changed.connect( self._update_acquirer_controller, )
def __init__(self) -> None: self._loop = asyncio.get_event_loop() self.bn_camera = BoxBindable(None) # type: Bindable[Optional[Camera]] self.bn_num_frames = BoxBindable(1) self.bn_frame_interval = BoxBindable( None) # type: Bindable[Optional[float]]
def __init__(self) -> None: self.bn_inner_density = BoxBindable( math.nan) # type: Bindable[Optional[float]] self.bn_outer_density = BoxBindable( math.nan) # type: Bindable[Optional[float]] self.bn_needle_width = BoxBindable( math.nan) # type: Bindable[Optional[float]] self.bn_gravity = BoxBindable( math.nan) # type: Bindable[Optional[float]]
def __init__(self) -> None: self.bn_save_dir_parent = BoxBindable(None) # type: Bindable[Optional[Path]] self.bn_save_dir_name = BoxBindable('') self.angle_figure_opts = FigureOptions( should_save=True, dpi=300, size_w=15, size_h=9 )
def __init__(self, in_analyses: Bindable[Sequence[ConanAnalysis]]) -> None: self._bn_analyses = in_analyses self._tracked_analyses = [] self._tracked_analysis_unbind_tasks = {} self.bn_left_angle_data = BoxBindable((tuple(), tuple())) self.bn_right_angle_data = BoxBindable((tuple(), tuple())) self._bn_analyses.on_changed.connect(self._hdl_analyses_changed) self._hdl_analyses_changed()
def __init__(self, in_analyses: Bindable[Sequence[IFTDropAnalysis]]) -> None: self._bn_analyses = in_analyses self._tracked_analyses = [] self._tracked_analysis_unbind_tasks = {} self.bn_ift_data = BoxBindable((tuple(), tuple())) self.bn_volume_data = BoxBindable((tuple(), tuple())) self.bn_surface_area_data = BoxBindable((tuple(), tuple())) self._bn_analyses.on_changed.connect(self._hdl_analyses_changed) self._hdl_analyses_changed()
def _start_fit(self, image: np.ndarray, image_timestamp: float) -> None: assert self._image is None self._image = image self._image_timestamp = image_timestamp # Set given image to be readonly to prevent introducing some accidental bugs. self._image.flags.writeable = False extracted_features = self._do_extract_features(BoxBindable(self._image)) young_laplace_fit = self._do_young_laplace_fit(extracted_features) physical_properties = self._do_calculate_physprops(extracted_features, young_laplace_fit) self._extracted_features = extracted_features self._young_laplace_fit = young_laplace_fit self._physical_properties = physical_properties self._bind_fit() self.bn_image.poke() self.bn_image_timestamp.poke() young_laplace_fit.bn_is_busy.on_changed.connect( self._hdl_young_laplace_fit_is_busy_changed ) self.bn_status.set(self.Status.FITTING)
def __init__(self, do_exit: Callable[[], Any], *, loop: asyncio.AbstractEventLoop) -> None: self._loop = loop self._do_exit = do_exit self._feature_extractor_params = FeatureExtractorParams() self._conancalc_params = ContactAngleCalculatorParams() self._bn_analyses = BoxBindable( tuple()) # type: Bindable[Sequence[ConanAnalysis]] self._analyses_saved = False self.image_acquisition = ImageAcquisitionModel() self.image_acquisition.use_acquirer_type(AcquirerType.LOCAL_STORAGE) self.image_processing = ConanImageProcessingModel( image_acquisition=self.image_acquisition, feature_extractor_params=self._feature_extractor_params, conancalc_params=self._conancalc_params, do_extract_features=self.extract_features, ) self.results = ConanResultsModel( in_analyses=self._bn_analyses, do_cancel_analyses=self.cancel_analyses, do_save_analyses=self.save_analyses, create_save_options=self._create_save_options, check_if_safe_to_discard=self.check_if_safe_to_discard_analyses, )
def __init__( self, *, image_acquisition: ImageAcquisitionModel, feature_extractor_params: FeatureExtractorParams, conancalc_params: ContactAngleCalculatorParams, do_extract_features: Callable[ [Bindable[np.ndarray], FeatureExtractorParams], FeatureExtractor] ) -> None: self._image_acquisition = image_acquisition self._feature_extractor_params = feature_extractor_params self._conancalc_params = conancalc_params self._do_extract_features = do_extract_features self.bn_active_tool = BoxBindable(ToolID.DROP_REGION) region_clip = AccessorBindable(getter=self._get_region_clip) self.drop_region_plugin = DefineRegionPluginModel( in_region=self._feature_extractor_params.bn_drop_region_px, in_clip=region_clip, ) self.surface_plugin = DefineLinePluginModel( in_line=self._conancalc_params.bn_surface_line_px, in_clip=region_clip, ) self.foreground_detection_plugin = ForegroundDetectionPluginModel( feature_extractor_params=feature_extractor_params, ) self.preview_plugin = ConanPreviewPluginModel( image_acquisition=image_acquisition, feature_extractor_params=feature_extractor_params, do_extract_features=do_extract_features, )
def __init__( self, *, image_acquisition: ImageAcquisitionModel, feature_extractor_params: FeatureExtractorParams, do_extract_features: Callable[ [Bindable[np.ndarray], FeatureExtractorParams], FeatureExtractor] ) -> None: self._image_acquisition = image_acquisition self._feature_extractor_params = feature_extractor_params self._do_extract_features = do_extract_features self.bn_active_tool = BoxBindable(ToolID.DROP_REGION) region_clip = AccessorBindable(getter=self._get_region_clip) self.drop_region_plugin = DefineRegionPluginModel( in_region=self._feature_extractor_params.bn_drop_region_px, in_clip=region_clip, ) self.needle_region_plugin = DefineRegionPluginModel( in_region=self._feature_extractor_params.bn_needle_region_px, in_clip=region_clip, ) self.edge_detection_plugin = EdgeDetectionPluginModel( feature_extractor_params=feature_extractor_params, ) self.preview_plugin = IFTPreviewPluginModel( image_acquisition=image_acquisition, feature_extractor_params=feature_extractor_params, do_extract_features=do_extract_features, )
def __init__(self, camera_index: int) -> None: self._vc = cv2.VideoCapture(camera_index) self.bn_alive = BoxBindable(True) if not self.check_vc_works(timeout=5): raise ValueError('Camera failed to open.') # For some reason, on some cameras, the first few images captured will be dark. Consume those images now so the # camera will be "fully operational" after initialisation. for i in range(self._PRECAPTURE): self._vc.read()
def _do_init( self, in_status: Bindable[ResultsFooterStatus], in_progress: Bindable[float], in_time_elapsed: Bindable[float], in_time_remaining: Bindable[float], do_back: Callable[[], Any], do_cancel: Callable[[], Any], do_save: Callable[[], Any], ) -> None: self._bn_status = in_status self._bn_time_remaining = in_time_remaining self._do_back = do_back self._do_cancel = do_cancel self._do_save = do_save self.bn_progress = in_progress self.bn_progress_label = BoxBindable('') self.bn_time_elapsed = in_time_elapsed self.bn_time_remaining = BoxBindable(math.nan) self.__event_connections = []
def __init__(self, value: ValueType, *, errors_out: Optional[Bindable[Set[ErrorType]]] = None, on_user_finished_editing: Optional[Event] = None) -> None: if errors_out is None: errors_out = BoxBindable(set()) # type: Bindable[Set[ErrorType]] if on_user_finished_editing is None: on_user_finished_editing = Event() self.value = value self.errors_out = errors_out self.on_user_finished_editing = on_user_finished_editing
def __init__(self, *, loop: asyncio.AbstractEventLoop) -> None: self._loop = loop self.bn_mode = BoxBindable(AppMode.MAIN_MENU) self.main_menu = MainMenuModel( do_launch_ift=( lambda: self.bn_mode.set(AppMode.IFT) ), do_launch_conan=( lambda: self.bn_mode.set(AppMode.CONAN) ), do_exit=( lambda: self.bn_mode.set(AppMode.QUIT) ), )
def __init__(self, errors_in: Bindable[Set[ErrorType]], errors_out: Bindable[Set[ErrorType]]) -> None: self._errors_in = errors_in self.__destroyed = False self.__cleanup_tasks = [] self._is_showing_errors = BoxBindable(False) self.__cleanup_tasks.append(lambda: self._is_showing_errors.set(False)) data_bindings = [ errors_out.bind_from( bn_apply(lambda x, y: x if y else set(), self._errors_in, self._is_showing_errors)) ] self.__cleanup_tasks.extend(db.unbind for db in data_bindings)
def _do_init(self, in_analysis: Bindable[Optional[ConanAnalysis]]) -> None: self._bn_analysis = in_analysis self._analysis_unbind_tasks = [] self.bn_image = BoxBindable(None) self.bn_left_angle = BoxBindable(math.nan) self.bn_left_point = BoxBindable(Vector2(math.nan, math.nan)) self.bn_right_angle = BoxBindable(math.nan) self.bn_right_point = BoxBindable(Vector2(math.nan, math.nan)) self.bn_surface_line = BoxBindable(None) self.__event_connections = []
def _start_fit(self, image: np.ndarray, image_timestamp: float) -> None: assert self._image is None self._image = image self._image_timestamp = image_timestamp # Set given image to be readonly to prevent introducing some accidental bugs. self._image.flags.writeable = False extracted_features = self._do_extract_features(BoxBindable( self._image)) calculated_conan = self._do_calculate_conan(extracted_features) self._extracted_features = extracted_features self._calculated_conan = calculated_conan self._bind_fit() self.bn_image.poke() self.bn_image_timestamp.poke() self.bn_status.set(self.Status.FINISHED)
def __init__(self, features: FeatureExtractor, params: ContactAngleCalculatorParams) -> None: self._features = features self.params = params self.bn_left_tangent = BoxBindable(np.poly1d((math.nan, math.nan))) self.bn_left_angle = BoxBindable(math.nan) self.bn_left_point = BoxBindable(Vector2(math.nan, math.nan)) self.bn_right_tangent = BoxBindable(np.poly1d((math.nan, math.nan))) self.bn_right_angle = BoxBindable(math.nan) self.bn_right_point = BoxBindable(Vector2(math.nan, math.nan)) # Recalculate when inputs change features.bn_drop_profile_px.on_changed.connect(self._recalculate) params.bn_surface_line_px.on_changed.connect(self._recalculate) self._recalculate()
def __init__( self, in_analyses: Bindable[Sequence[IFTDropAnalysis]], do_cancel_analyses: Callable[[], Any], do_save_analyses: Callable[[IFTAnalysisSaverOptions], Any], create_save_options: Callable[[], IFTAnalysisSaverOptions], check_if_safe_to_discard: Callable[[], bool], ): self.bn_analyses = in_analyses self._do_cancel_analyses = do_cancel_analyses self._do_save_analyses = do_save_analyses self._create_save_options = create_save_options self._check_if_safe_to_discard = check_if_safe_to_discard self.bn_selection = BoxBindable( None) # type: Bindable[Optional[IFTDropAnalysis]] self.individual = IndividualModel( in_analyses=self.bn_analyses, bind_selection=self.bn_selection, ) self.graphs = GraphsModel(in_analyses=self.bn_analyses, ) self._tracked_analyses = [] self._analysis_untrack_tasks = {} self.bn_fitting_status = AccessorBindable( getter=self._get_fitting_status) self.bn_analyses_time_start = AccessorBindable( getter=self._get_analyses_time_start) self.bn_analyses_time_est_complete = AccessorBindable( getter=self._get_analyses_time_est_complete) self.bn_analyses_completion_progress = AccessorBindable( getter=self._get_analyses_completion_progress) self.bn_analyses.on_changed.connect(self._hdl_analyses_changed)
def __init__(self) -> None: self.bn_drop_region_px = BoxBindable(None) self.bn_thresh = BoxBindable(30)
def __init__(self, pages: Iterable) -> None: self._pages = tuple(pages) self.bn_current_page = BoxBindable(self._pages[0])
def __init__( self, input_image: InputImage, do_extract_features: Callable[[Bindable[np.ndarray]], FeatureExtractor], do_calculate_conan: Callable[[FeatureExtractor], ContactAngleCalculator], ) -> None: self._loop = asyncio.get_event_loop() self._time_start = time.time() self._time_end = math.nan self._input_image = input_image self._do_extract_features = do_extract_features self._do_calculate_conan = do_calculate_conan self._status = self.Status.WAITING_FOR_IMAGE self.bn_status = AccessorBindable( getter=self._get_status, setter=self._set_status, ) self._image = None # type: Optional[np.ndarray] # The time (in Unix time) that the image was captured. self._image_timestamp = math.nan # type: float self._extracted_features = None # type: Optional[FeatureExtractor] self._calculated_conan = None # type: Optional[ContactAngleCalculator] self.bn_image = AccessorBindable(self._get_image) self.bn_image_timestamp = AccessorBindable(self._get_image_timestamp) # Attributes from ContactAngleCalculator self.bn_left_angle = BoxBindable(math.nan) self.bn_left_tangent = BoxBindable(np.poly1d((math.nan, math.nan))) self.bn_left_point = BoxBindable(Vector2(math.nan, math.nan)) self.bn_right_angle = BoxBindable(math.nan) self.bn_right_tangent = BoxBindable(np.poly1d((math.nan, math.nan))) self.bn_right_point = BoxBindable(Vector2(math.nan, math.nan)) self.bn_surface_line = BoxBindable(None) # Attributes from FeatureExtractor self.bn_drop_region = BoxBindable(None) self.bn_drop_profile_extract = BoxBindable(None) # Log self.bn_is_done = AccessorBindable(getter=self._get_is_done) self.bn_is_cancelled = AccessorBindable(getter=self._get_is_cancelled) self.bn_progress = AccessorBindable(self._get_progress) self.bn_time_start = AccessorBindable(self._get_time_start) self.bn_time_est_complete = AccessorBindable( self._get_time_est_complete) self.bn_status.on_changed.connect(self.bn_is_done.poke) self.bn_status.on_changed.connect(self.bn_progress.poke) self._loop.create_task(self._input_image.read()).add_done_callback( self._hdl_input_image_read)
def __init__(self) -> None: self.bn_surface_line_px = BoxBindable( None) # type: Bindable[Optional[Line2]]
def __init__( self, input_image: InputImage, do_extract_features: Callable[[Bindable[np.ndarray]], FeatureExtractor], do_young_laplace_fit: Callable[[FeatureExtractor], YoungLaplaceFitter], do_calculate_physprops: Callable[[FeatureExtractor, YoungLaplaceFitter], PhysicalPropertiesCalculator] ) -> None: self._loop = asyncio.get_event_loop() self._time_start = time.time() self._time_end = math.nan self._input_image = input_image self._do_extract_features = do_extract_features self._do_young_laplace_fit = do_young_laplace_fit self._do_calculate_physprops = do_calculate_physprops self._status = self.Status.WAITING_FOR_IMAGE self.bn_status = AccessorBindable( getter=self._get_status, setter=self._set_status, ) self._image = None # type: Optional[np.ndarray] # The time (in Unix time) that the image was captured. self._image_timestamp = math.nan # type: float self._extracted_features = None # type: Optional[FeatureExtractor] self._physical_properties = None # type: Optional[PhysicalPropertiesCalculator] self._young_laplace_fit = None # type: Optional[YoungLaplaceFitter] self.bn_image = AccessorBindable(self._get_image) self.bn_image_timestamp = AccessorBindable(self._get_image_timestamp) # Attributes from YoungLaplaceFitter self.bn_bond_number = BoxBindable(math.nan) self.bn_apex_coords_px = BoxBindable(Vector2(math.nan, math.nan)) self.bn_apex_radius_px = BoxBindable(math.nan) self.bn_rotation = BoxBindable(math.nan) self.bn_drop_profile_fit = BoxBindable(None) self.bn_residuals = BoxBindable(None) # Attributes from PhysicalPropertiesCalculator self.bn_interfacial_tension = BoxBindable(math.nan) self.bn_volume = BoxBindable(math.nan) self.bn_surface_area = BoxBindable(math.nan) self.bn_apex_radius = BoxBindable(math.nan) self.bn_worthington = BoxBindable(math.nan) # Attributes from FeatureExtractor self.bn_drop_region = BoxBindable(None) self.bn_needle_region = BoxBindable(None) self.bn_drop_profile_extract = BoxBindable(None) self.bn_needle_profile_extract = BoxBindable(None) self.bn_needle_width_px = BoxBindable(math.nan) # Log self.bn_log = BoxBindable('') self.bn_is_done = AccessorBindable(getter=self._get_is_done) self.bn_is_cancelled = AccessorBindable(getter=self._get_is_cancelled) self.bn_progress = AccessorBindable(self._get_progress) self.bn_time_start = AccessorBindable(self._get_time_start) self.bn_time_est_complete = AccessorBindable(self._get_time_est_complete) self.bn_status.on_changed.connect(self.bn_is_done.poke) self.bn_status.on_changed.connect(self.bn_progress.poke) self._loop.create_task(self._input_image.read()).add_done_callback(self._hdl_input_image_read)
def __init__(self) -> None: self.bn_images = BoxBindable( tuple()) # type: Bindable[Sequence[np.ndarray]] self.bn_frame_interval = BoxBindable( None) # type: Bindable[Optional[int]]
def __init__(self) -> None: self.bn_needle_region_px = BoxBindable(None) self.bn_drop_region_px = BoxBindable(None) self.bn_canny_min = BoxBindable(30) self.bn_canny_max = BoxBindable(60)