class IlluminationResponse: """ A description of the illumination response of a fluorophore at a certain wavelength. """ wavelength: float = extended_field(observable_property( "_wavelength", default=0.0, signal_name="basic_field_changed"), description="wavelength [nm]") cross_section_off_to_on: Union[float, Multivalue[float]] = extended_field( observable_property("_cross_section_off_to_on", default=0.0, signal_name="basic_field_changed"), description="ON cross section", accept_multivalues=True) cross_section_on_to_off: Union[float, Multivalue[float]] = extended_field( observable_property("_cross_section_on_to_off", default=0.0, signal_name="basic_field_changed"), description="OFF cross section", accept_multivalues=True) cross_section_emission: Union[float, Multivalue[float]] = extended_field( observable_property("_cross_section_emission", default=0.0, signal_name="basic_field_changed"), description="emission cross section", accept_multivalues=True) # Methods def __str__(self) -> str: return f"{self.wavelength} nm"
class FrcResultsModel: """ Model for the FRC/resolution results widget. """ currentPlot: Plot = observable_property("_currentPlot", default=Plot.frc, signal_name="currentPlotChanged", emit_arg_name="currentPlot") crosshairEnabled: bool = observable_property( "_crosshairEnabled", default=True, signal_name="crosshairToggled", emit_arg_name="crosshairEnabled") frcCurve: Optional[Tuple[np.ndarray, np.ndarray]] = observable_property( "_frcCurve", default=None, signal_name="frcCurveChanged", emit_arg_name="frcCurve") viewOptions: ViewOptions = observable_property( "_viewOptions", default=ViewOptions(), signal_name="viewOptionsChanged", emit_arg_name="viewOptions")
class DetectorProperties: """ A description of a detector. """ readout_noise: Union[float, Multivalue[float]] = extended_field( observable_property("_readout_noise", default=0.0, signal_name="basic_field_changed"), description="readout noise [rms]", accept_multivalues=True ) quantum_efficiency: Union[float, Multivalue[float]] = extended_field( observable_property("_quantum_efficiency", default=0.75, signal_name="basic_field_changed"), description="quantum efficiency", accept_multivalues=True ) camera_pixel_size: Optional[Union[float, Multivalue[float]]] = extended_field( # nanometres (if point detector: None) observable_property("_camera_pixel_size", default=None, signal_name="basic_field_changed"), description="camera pixel size [nm]", accept_multivalues=True ) def get_total_readout_noise_var(self, canvas_inner_radius_nm: float, pinhole_function: Pattern) -> float: """ Returns the total readout noise of the detector as a variance. """ if self.camera_pixel_size is not None: pinhole_sum = ( pinhole_function.get_numpy_array( canvas_inner_radius_nm, self.camera_pixel_size ) ** 2 ).sum() return pinhole_sum * self.readout_noise ** 2 else: return self.readout_noise ** 2
class Preferences: """ A description of the persistent preferences that the user should be able to change in the program. """ precacheFrcCurves: bool = observable_property( "_precacheFrcCurves", default=True, signal_name="basicFieldChanged") precacheExpectedImages: bool = observable_property( "_precacheExpectedImages", default=False, signal_name="basicFieldChanged") cacheKernels2D: bool = observable_property("_cacheKernels2D", default=True, signal_name="basicFieldChanged") # Methods @staticmethod def initFile() -> None: """ Creates the preferences file if it does not exist. """ if not os.path.isfile(_preferencesFilePath): Preferences.save(Preferences()) else: Preferences.get() @staticmethod def get() -> "Preferences": """ Returns the persistent preferences object. It will be loaded from the disk if that has not already been done. """ global _preferences if _preferences is None: with open(_preferencesFilePath, "r") as jsonFile: json = jsonFile.read() persistentContainer = PersistentContainer[ Preferences].from_json_with_converted_dicts( json, Preferences) _preferences = persistentContainer.data return _preferences @staticmethod def save(preferences: "Preferences"): """ Saves the given persistent preferences object to memory as well as the disk. """ global _preferences _preferences = preferences with open(_preferencesFilePath, "w") as jsonFile: persistentContainer = PersistentContainer[Preferences](preferences) jsonFile.write(persistentContainer.to_json(indent=2))
class KernelResultsModel: """ Model for the kernel results widget. """ kernelType: KernelType = observable_property( "_kernelType", default=KernelType.exp_kernel, signal_name="kernelTypeChanged", emit_arg_name="kernelType") kernels2D: Optional[np.ndarray] = observable_property( "_kernels2D", default=None, signal_name="kernels2DChanged", emit_arg_name="kernels2D")
class SimulationSettings: """ Advanced simulation settings. """ canvas_inner_radius: float = observable_property( # nanometres "_canvas_inner_radius", default=500.0, signal_name="canvas_inner_radius_changed", emit_arg_name="canvas_inner_radius" ) num_kernel_detection_iterations: int = observable_property( "_num_kernel_detection_iterations", default=500000, signal_name="num_kernel_detection_iterations_changed", emit_arg_name="num_kernel_detection_iterations" )
class SimulationResultsView: """ A representation of a view of results of a full simulation run. """ results: Optional[SimulationResults] = observable_property( "_results", default=None, signal_name="resultsChanged", emit_arg_name="results" ) inspectedMultivalueIndex: int = observable_property( # -1 if no multivalue inspected "_inspectedMultivalueIndex", default=-1, signal_name="inspectedMultivalueIndexChanged", emit_arg_name="inspectedMultivalueIndex" ) multivalueValueIndices: List[int] = observable_property( # viewed multivalue value indices "_multivalueValueIndices", default=list, signal_name="multivalueValueIndexChanged", emit_arg_name="multivalueValueIndices" ) displayableSample: Optional[DisplayableSample] = observable_property( # loaded sample image "_displayableSample", default=None, signal_name="displayableSampleChanged", emit_arg_name="displayableSample" ) threshold: float = observable_property( "_threshold", default=0.15, signal_name="thresholdChanged", emit_arg_name="threshold" ) def precacheAllResults(self) -> None: """ Pre-caches all results from the simulation. """ if self.results is not None: if self.displayableSample is None: self.results.clear_cache(clear_expected_image=True) self.results.precache(cache_kernels2d=True, cache_frc_curves=True, cache_expected_image_for=self.displayableSample) def setMultivalueValue(self, indexOfMultivalue: int, indexInMultivalue: int) -> None: """ Sets which index in the list of possible values (indexInMultivalue) should be used when displaying the results. indexOfMultivalue gives the index of the multivalue to adjust. """ self.multivalueValueIndices[indexOfMultivalue] = indexInMultivalue self.multivalueValueIndexChanged.emit(self.multivalueValueIndices)
class ExplicitSampleProperties: """ An explicit description of sample-related properties in an environment. """ input_power: Union[float, Multivalue[float]] = extended_field( observable_property("_input_power", default=1.0, signal_name="basic_field_changed"), description="input power", accept_multivalues=True) D_origin: Union[float, Multivalue[float]] = extended_field( observable_property("_D_origin", default=1.0, signal_name="basic_field_changed"), description="D(0, 0)", accept_multivalues=True)
class ImagingSystemSettings: """ A description of an imaging system. """ optical_psf: Pattern = extended_field(default_factory=Pattern, description="optical PSF") pinhole_function: Pattern = extended_field(default_factory=Pattern, description="pinhole function") scanning_step_size: Union[float, Multivalue[float]] = extended_field( observable_property("_scanning_step_size", default=10.0, signal_name="basic_field_changed"), description="scanning step size [nm]", accept_multivalues=True ) refractive_index: float = observable_property( "_refractive_index", default=RefractiveIndex.oil.value, signal_name="basic_field_changed" )
class SampleProperties: """ A description of sample-related properties in an environment. """ basic_properties: ExplicitSampleProperties = extended_field( observable_property("_basic_properties", default=ExplicitSampleProperties(), signal_name="data_loaded"), description="sample") structure: Optional[SampleStructure] = extended_field( observable_property("_structure", default=None, signal_name="data_loaded"), description="structure") def load_structure(self, structure: SampleStructure) -> None: """ Loads a sample structure. """ self.basic_properties.input_power = 1.0 self.basic_properties.D_origin = 1.0 self.structure = structure def unload_structure(self) -> None: """ Unloads any currently loaded sample structure. """ self.structure = None def get_combined_properties(self, px_size_nm: float) -> ExplicitSampleProperties: """ Returns explicit sample properties. Properties derived from any loaded sample structure will take precedence over properties defined in basic_properties. """ if self.structure is not None: return self.structure.get_explicit_properties(px_size_nm) elif self.basic_properties is not None: return self.basic_properties else: raise Exception("basic_properties or structure must be set!")
class Pulse: """ A description of a laser pulse. """ wavelength: Union[float, Multivalue[float]] = extended_field( observable_property("_wavelength", default=0.0, signal_name="basic_field_changed"), description="wavelength [nm]", accept_multivalues=True ) duration: Union[float, Multivalue[float]] = extended_field( observable_property("_duration", default=0.0, signal_name="basic_field_changed"), description="duration [ms]", accept_multivalues=True ) max_intensity: Union[float, Multivalue[float]] = extended_field( observable_property("_max_intensity", default=0.0, signal_name="basic_field_changed"), description="max intensity [kW/cm²]", accept_multivalues=True ) illumination_pattern: Pattern = extended_field(default_factory=Pattern, description="illumination pattern")
class RunInstance: """ A description of all parameters part of a simulation that can be run. """ fluorophore_settings: FluorophoreSettings = extended_field( observable_property("_fluorophore_settings", default=FluorophoreSettings, signal_name="fluorophore_settings_loaded", emit_arg_name="fluorophore_settings"), description="fluorophore settings") imaging_system_settings: ImagingSystemSettings = extended_field( observable_property("_imaging_system_settings", default=ImagingSystemSettings, signal_name="imaging_system_settings_loaded", emit_arg_name="imaging_system_settings"), description="imaging system settings") pulse_scheme: PulseScheme = extended_field(observable_property( "_pulse_scheme", default=PulseScheme, signal_name="pulse_scheme_loaded", emit_arg_name="pulse_scheme"), description="pulse scheme") sample_properties: SampleProperties = extended_field( observable_property("_sample_properties", default=SampleProperties, signal_name="sample_properties_loaded", emit_arg_name="sample_properties"), description="sample properties") detector_properties: DetectorProperties = extended_field( observable_property("_detector_properties", default=DetectorProperties, signal_name="detector_properties_loaded", emit_arg_name="detector_properties"), description="detector properties") simulation_settings: SimulationSettings = extended_field( observable_property("_simulation_settings", default=SimulationSettings, signal_name="simulation_settings_loaded", emit_arg_name="simulation_settings"), description="simulation settings") # Methods def simulate(self, *, cache_kernels2d: bool = True, precache_frc_curves: bool = True, preprocessing_finished_callback: Optional[Signal] = None, progress_updated_callback: Optional[Signal] = None): """ Runs the simulation and returns the results. """ return simulate( deepcopy(self), cache_kernels2d=cache_kernels2d, precache_frc_curves=precache_frc_curves, abort_signal=self._abort_signal, preprocessing_finished_callback=preprocessing_finished_callback, progress_updated_callback=progress_updated_callback) def abort_running_simulations(self) -> None: """ Emits a signal to abort any running simulations. Note that the simulations may not terminate immediately after this method returns. """ self._abort_signal.emit()