Skip to content
Snippets Groups Projects
Commit df56d846 authored by Benedikt Burger's avatar Benedikt Burger
Browse files

Add MainWindow

parent 5933d784
No related branches found
No related tags found
No related merge requests found
......@@ -5,8 +5,10 @@ SNLO-Helper helps to use [SNLO](https://as-photonics.com/products/snlo/) softwar
An autoclicker clicks different buttons and fills fields in order to automate SNLO simulations.
Afterwards, it can retrieve the results and return them as a dictionary.
Note that the script does use your mouse and keyboard, so you should not interact with the computer at the same time.
The autoclicker can be interrupted by moving the mouse into the top right corner of the screen.
Attention:
- The script does use your mouse and keyboard, so you should not interact with the computer at the same time.
- The script uses predefined positions of the windows, so **do not move the windows**.
- The autoclicker can be interrupted by moving the mouse into the top left corner of the screen.
## Installation
......@@ -19,10 +21,10 @@ Install it executing `pip install -e .` in this folder or via `pip install git+h
### Quick Start
1. Start SNLO on your computer
2. Import `snlohelper.snlo` as a starting point.
3. If your screen resolution differs from HD, you have to set screenfactors with `utils.set_screenfactors`.
That will rescale all positions to your current screen resolution.
4. Open the desired method and execute it.
2. Import `snlohelper.main_window.MainWindow` as a starting point.
3. Create an instande `mw = MainWindow`
4. Open the desired function: `ri = mw.open_function(Functions.REF_INDEX)`
5. Execute it `no, ne = ri.refractive_indices(Wavelength=1234)`
Here is a small snippet how to do a 2D mix of long pulses:
```
......@@ -42,9 +44,9 @@ For more examples see the `examples` folder.
### General usage
* The `main_window.open_function` method allows to open any SNLO function of the main window.
* The `main_window.MainWindow` class manages the main window.
* For several functions exists a module containing a class, which in turn allows to configure the function, to run the calculation, and to extract the result.
1. You start that class, for example `mix = two_d_mix_lp.TwoDMixLp()`.
1. You start that class, for example `mix = two_d_mix_lp.TwoDMixLp()` or `mix = MainWindow().open_function("2D-Mix-LP")`.
2. You can configure it giving a configuration dictionary (the keys correspond to the names) with `mix.configure({"Wavelengths": [1064, None, None]})`
3. You can run it with `mix.run()`
4. With `results = mix.read_results()` you can extract the resulting text.
......
......@@ -2,7 +2,7 @@ import time
from typing import Any, Optional, Protocol
from .utils import Point, gui, scale, get_content_complete, set_value
from .main_window import Functions, open_function
from .functions import Functions, open_function
class BaseFunction(Protocol):
......
from .main_window import open_function, Functions
from typing import Optional
from .base_function import BaseFunction
from .functions import open_function, Functions
from .utils import Point, gui, scale, set_value, get_value_complete
......@@ -41,3 +44,37 @@ def focus(
radcurv = get_value_complete(_dict_focus["Radius of curv. (mm)"])
angle = get_value_complete(_dict_focus["Far field ang air (mrad)"])
return zr, diameter, radcurv, angle
class Focus(BaseFunction):
_function = Functions.FOCUS
def __init__(self) -> None:
super().__init__()
self._configuration_pos = {key: [value] for key, value in _dict_focus.items()}
def read_results(self) -> list[str]:
return super().read_results()
def focus(
self,
wavelength_nm: Optional[float] = None,
ref_index: Optional[float] = None,
fwhm_mm: Optional[float] = None,
focus_pos_mm: Optional[float] = None,
) -> tuple[float, float, float, float]:
self.configure(
{
"Wavelength (nm)": wavelength_nm,
"Refractive Index": ref_index,
"Waist size (mm)": fwhm_mm,
# Set face to focus and dist to focus to same value gives values in air at face
"Face to focus (mm)": focus_pos_mm,
"Dist. to focus (mm)": focus_pos_mm,
}
)
zr = get_value_complete(_dict_focus["Rayleigh z in xtal (mm)"])
diameter = get_value_complete(_dict_focus["Beam size (mm)"])
radcurv = get_value_complete(_dict_focus["Radius of curv. (mm)"])
angle = get_value_complete(_dict_focus["Far field ang air (mrad)"])
return zr, diameter, radcurv, angle
from enum import StrEnum
from .utils import Point, gui, scale
# coordinates of the functions (in FHD standard)
_functions_coord: dict[str, Point] = {
"Ref. Ind.": (66, 46),
"Qmix": (66, 66),
"Bmix": (66, 93),
"QPM": (66, 120),
"Opoangles": (66, 146),
"Ncpm": (66, 173),
"GVM": (66, 200),
"PW-mix-LP": (66, 233),
"PW-mix-SP": (66, 260),
"PW-mix-BB": (66, 286),
"2D-mix-LP": (66, 313),
"2D-mix-SP": (66, 340),
"PW-cav-LP": (66, 366),
"PW-OPO-SP": (66, 393),
"PW-OPO-BB": (66, 420),
"2D-cav-LP": (66, 446),
"Focus": (66, 473),
"Cavity": (66, 500),
}
class Functions(StrEnum):
"""Enum for the functions."""
REF_INDEX = "Ref. Ind."
QMIX = "Qmix"
BMIX = "Bmix"
QPM = "QPM"
OPO_ANGLES = "Opoangles"
NCPM = "Ncpm"
GVM = "GVM"
PW_MIX_LP = "PW-mix-LP"
PW_MIX_SP = "PW-mix-SP"
PW_MIX_BB = "PW-mix-BB"
TWOD_MIX_LP = "2D-mix-LP"
TWOD_MIX_SP = "2D-mix-SP"
PW_CAV_LP = "PW-cav-LP"
PW_OPO_SP = "PW-OPO-SP"
PW_OPO_BB = "PW-OPO-BB"
TWOD_CAV_LP = "2D-cav-LP"
FOCUS = "Focus"
CAVITY = "Cavity"
def open_function(key: str | Functions) -> None:
"""opens function according to key"""
gui.click(*scale(*_functions_coord[key]))
......@@ -2,60 +2,38 @@
The SNLO main window
"""
from enum import StrEnum
from .utils import Point, gui, scale
# coordinates of the functions (in FHD standard)
_functions_coord: dict[str, Point] = {
"Ref. Ind.": (66, 46),
"Qmix": (66, 66),
"Bmix": (66, 93),
"QPM": (66, 120),
"Opoangles": (66, 146),
"Ncpm": (66, 173),
"GVM": (66, 200),
"PW-mix-LP": (66, 233),
"PW-mix-SP": (66, 260),
"PW-mix-BB": (66, 286),
"2D-mix-LP": (66, 313),
"2D-mix-SP": (66, 340),
"PW-cav-LP": (66, 366),
"PW-OPO-SP": (66, 393),
"PW-OPO-BB": (66, 420),
"2D-cav-LP": (66, 446),
"Focus": (66, 473),
"Cavity": (66, 500),
from typing import Optional
from .utils import gui, scale, get_screenfactors, set_screenfactors, Point
from .functions import Functions, open_function
from .base_function import BaseFunction
from .ref_index import RefractiveIndex
from .focus import Focus
from .two_d_mix_lp import TwoDMixLP
from .two_d_mix_sp import TwoDMixSP
function_classes = {
Functions.REF_INDEX: RefractiveIndex,
Functions.TWOD_MIX_LP: TwoDMixLP,
Functions.TWOD_MIX_SP: TwoDMixSP,
Functions.FOCUS: Focus,
}
class Functions(StrEnum):
"""Enum for the functions."""
REF_INDEX = "Ref. Ind."
QMIX = "Qmix"
BMIX = "Bmix"
QPM = "QPM"
OPO_ANGLES = "Opoangles"
NCPM = "Ncpm"
GVM = "GVM"
PW_MIX_LP = "PW-mix-LP"
PW_MIX_SP = "PW-mix-SP"
PW_MIX_BB = "PW-mix-BB"
TWOD_MIX_LP = "2D-mix-LP"
TWOD_MIX_SP = "2D-mix-SP"
PW_CAV_LP = "PW-cav-LP"
PW_OPO_SP = "PW-OPO-SP"
PW_OPO_BB = "PW-OPO-BB"
TWOD_CAV_LP = "2D-cav-LP"
FOCUS = "Focus"
CAVITY = "Cavity"
def open_function(key: str | Functions) -> None:
"""opens function according to key"""
gui.click(*scale(*_functions_coord[key]))
def close_snlo() -> None:
gui.click(*scale(95, 14))
class MainWindow:
_close_pos = (95, 14)
def __init__(self, screenfactors: Optional[Point] = None, **kwargs) -> None:
super().__init__(**kwargs)
sf = get_screenfactors()
if sf is None or screenfactors is not None:
set_screenfactors(new_factors=screenfactors)
def close(self) -> None:
gui.click(*scale(self._close_pos))
def open_function(self, key: str | Functions) -> Optional[BaseFunction]:
open_function(key)
if key in function_classes:
return function_classes[key]()
......@@ -28,6 +28,12 @@ class RefractiveIndex(BaseFunction):
def refractive_indices(
self, Crystal=None, Temperature=None, theta=None, phi=None, Wavelength=None
) -> list[float]:
"""Get the refractive indices (o, e).
For the crystal, you have to use letters to press, for example "BB" to select the second
crystal starting with a "B". In order to ensure, that it starts correctly, use any other
letter first, e.g. "ABB".
"""
kwargs = {
"Crystal": Crystal,
"Temperature": Temperature,
......
......@@ -28,8 +28,8 @@ screen resolution.
"""
def get_screenfactors(standard: Point = (1920, 1080)) -> Point:
"""Get the scaling factor from Full HD to the current display resolution."""
def read_display_screenfactors(standard: Point = (1920, 1080)) -> Point:
"""Read the scaling factor from Full HD to the current display resolution."""
width, height = gui.size()
return standard[0] / width, standard[1] / height
......@@ -37,11 +37,20 @@ def get_screenfactors(standard: Point = (1920, 1080)) -> Point:
def set_screenfactors(new_factors: Optional[tuple[float, float]] = None) -> tuple[float, float]:
"""Set the screenfactors to `new_factors` or detect them automatically."""
global factors
factors = get_screenfactors() if new_factors is None else new_factors
factors = read_display_screenfactors() if new_factors is None else new_factors
return factors
def scale(x: float | Point, y: float | None = None) -> Point:
def get_screenfactors() -> Optional[tuple[float, float]]:
"""Get the current screenfactors or None, if not yet set."""
global factors
try:
return factors
except NameError:
return None
def scale(x: Union[float, Point], y: Optional[float] = None) -> Point:
"""Scale coordinates from the definition standard to the current screen."""
global factors
if isinstance(x, (list, tuple)):
......@@ -110,3 +119,11 @@ def set_value(position: Point, value: Any) -> None:
gui.press("delete")
gui.doubleClick()
gui.write(str(value))
def alt_tab() -> None:
gui.hotkey("alt", "tab")
def get_position() -> Point:
return gui.position()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment