├── demos ├── __init__.py ├── data │ ├── Thorlabs_LBF254_050_A.spd │ └── Thorlabs_AC127_050_A.spd ├── demo_tilted_image.py ├── demo_benchmark.py ├── demo_optimize_goptical.cc ├── demo_asphere.py ├── demo_anisotropic_mirror.py ├── demo_doublet.py ├── demo_prism.py ├── demo_anisotropic_ord_eo.py └── demo_zmx.py ├── tests ├── __init__.py ├── lenssystem.ZMX ├── baseline_images │ └── smoke_test │ │ └── doublet.png ├── smoke_test.py ├── test_ray_analysis.py └── test_optimize.py ├── freecad ├── PyrateWorkbench │ ├── paths.txt │ ├── __init__.py │ ├── Gui │ │ ├── __init__.py │ │ └── Resources │ │ │ ├── __init__.py │ │ │ ├── icons │ │ │ ├── __init__.py │ │ │ ├── pyrate_load_sys_icon.svg │ │ │ ├── pyrate_save_sys_icon.svg │ │ │ └── pyrate_material_icon.svg │ │ │ └── resources.qrc │ ├── build_rc.sh │ ├── metadata.txt │ ├── README.md │ ├── Qt │ │ ├── lcdialog.ui │ │ ├── dlg_functionsobject_edit.ui │ │ ├── dlg_surfacelist_edit.ui │ │ ├── dlg_functionsobject_add.ui │ │ ├── dlg_localcoords_add.ui │ │ ├── surfacedialog.ui │ │ ├── dlg_cwov_edit.ui │ │ ├── dlg_new_rotational_symmetric_system.ui │ │ └── dlg_optimization.ui │ ├── TaskPanel_SurfaceList_Edit.py │ ├── TaskPanel_Functions_Edit.py │ ├── Commands_Analysis.py │ ├── Object_NotSerializable.py │ ├── Commands_Surface.py │ ├── Commands_EditClassWithOptimizableVariables.py │ ├── Dialog_Optimization.py │ ├── Commands_Functions.py │ ├── Object_ClassWithOptimizableVariables.py │ ├── TaskPanel_Functions_Add.py │ ├── Object_MaterialCatalogue.py │ ├── Commands_FieldPoints.py │ ├── Interface_Identifiers.py │ ├── TaskPanel_LocalCoordinates_Add.py │ ├── Commands_Materials.py │ ├── Commands_Files.py │ └── Commands_Optimization.py ├── __init__.py └── Macros │ └── test_cwov_dialog.FCMacro ├── pyrateoptics ├── core │ ├── __init__.py │ ├── names │ │ ├── __init__.py │ │ ├── nouns.json │ │ ├── adjectives.json │ │ └── nltk_list_generator.py │ ├── README.md │ ├── observers.py │ ├── decorators.py │ ├── functionobjects_pool.py │ ├── base.py │ └── base_ui_transform.py ├── optimize │ ├── __init__.py │ ├── README.md │ └── optimize.py ├── raytracer │ ├── __init__.py │ ├── io │ │ ├── __init__.py │ │ └── README.md │ ├── analysis │ │ ├── __init__.py │ │ ├── README.md │ │ ├── optical_element_analysis.py │ │ └── surface_shape_analysis.py │ ├── material │ │ ├── __init__.py │ │ └── README.md │ ├── README.md │ ├── config │ │ └── raytracer.yaml │ ├── globalconstants.py │ ├── localcoordinatestreebase.py │ └── helpers_math.py └── sampling2d │ ├── __init__.py │ └── README.md ├── docs ├── rtfm │ ├── attic │ │ ├── pilot.jpg │ │ ├── mild_asphere.jpg │ │ ├── eikonal_equation_approximation.tex │ │ └── anisotropic_formulae.tex │ ├── graphics │ │ ├── pupil.jpg │ │ ├── pupil.odg │ │ ├── mild_asphere.jpg │ │ ├── time_of_flight.jpg │ │ ├── waveaberrations.jpg │ │ ├── boundary_wavevectors_1in.jpg │ │ ├── xyuv_on_axis_astigmatism.png │ │ ├── boundary_wavevectors_all8.jpg │ │ ├── boundary_wavevectors_1in.eps │ │ └── boundary_wavevectors_all8.eps │ └── pyrate.bib └── talk_euroscipy_2017 │ ├── talk.odp │ ├── figure_2.jpg │ └── reflex_camera_cc-by-sa_anuskafm_wikipedia.txt ├── images ├── pyrate_in_freecad.png ├── pyrate_mirror_system.png └── wiki │ ├── wiki_pyrate_grin.png │ ├── wiki_pyrate_prism.png │ ├── wiki_pyrate_focus_yz.png │ ├── wiki_pyrate_freecad.png │ ├── wiki_pyrate_freecad2.png │ ├── wiki_pyrate_rainbow.png │ ├── wiki_coordinate_systems.png │ ├── wiki_pyrate_grin_opti1.png │ ├── wiki_pyrate_grin_opti2.png │ ├── wiki_pyrate_grin_opti3.png │ ├── wiki_coordinate_systems2.png │ ├── wiki_coordinate_systems3.png │ ├── wiki_coordinate_systems4.png │ ├── wiki_pyrate_curved_mirrors.png │ └── wiki_pyrate_flat_mirrors.png ├── run_demos ├── .gitmodules ├── MANIFEST.in ├── requirements.in ├── .gitignore ├── .travis.yml ├── appveyor.yml ├── CONTRIBUTING.md ├── copyright_text_changer.py └── setup.py /demos/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/paths.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pyrateoptics/core/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pyrateoptics/optimize/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pyrateoptics/core/names/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pyrateoptics/raytracer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pyrateoptics/raytracer/io/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pyrateoptics/sampling2d/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Gui/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pyrateoptics/raytracer/analysis/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pyrateoptics/raytracer/material/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Gui/Resources/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Gui/Resources/icons/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /freecad/__init__.py: -------------------------------------------------------------------------------- 1 | __path__ = __import__('pkgutil').extend_path(__path__, __name__) 2 | -------------------------------------------------------------------------------- /tests/lenssystem.ZMX: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/tests/lenssystem.ZMX -------------------------------------------------------------------------------- /docs/rtfm/attic/pilot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/docs/rtfm/attic/pilot.jpg -------------------------------------------------------------------------------- /docs/rtfm/graphics/pupil.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/docs/rtfm/graphics/pupil.jpg -------------------------------------------------------------------------------- /docs/rtfm/graphics/pupil.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/docs/rtfm/graphics/pupil.odg -------------------------------------------------------------------------------- /images/pyrate_in_freecad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/images/pyrate_in_freecad.png -------------------------------------------------------------------------------- /docs/rtfm/attic/mild_asphere.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/docs/rtfm/attic/mild_asphere.jpg -------------------------------------------------------------------------------- /images/pyrate_mirror_system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/images/pyrate_mirror_system.png -------------------------------------------------------------------------------- /images/wiki/wiki_pyrate_grin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/images/wiki/wiki_pyrate_grin.png -------------------------------------------------------------------------------- /docs/talk_euroscipy_2017/talk.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/docs/talk_euroscipy_2017/talk.odp -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/build_rc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | pyside-rcc -py3 -o resources_rc.py Gui/Resources/resources.qrc 3 | -------------------------------------------------------------------------------- /images/wiki/wiki_pyrate_prism.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/images/wiki/wiki_pyrate_prism.png -------------------------------------------------------------------------------- /docs/rtfm/graphics/mild_asphere.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/docs/rtfm/graphics/mild_asphere.jpg -------------------------------------------------------------------------------- /docs/rtfm/graphics/time_of_flight.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/docs/rtfm/graphics/time_of_flight.jpg -------------------------------------------------------------------------------- /docs/talk_euroscipy_2017/figure_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/docs/talk_euroscipy_2017/figure_2.jpg -------------------------------------------------------------------------------- /images/wiki/wiki_pyrate_focus_yz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/images/wiki/wiki_pyrate_focus_yz.png -------------------------------------------------------------------------------- /images/wiki/wiki_pyrate_freecad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/images/wiki/wiki_pyrate_freecad.png -------------------------------------------------------------------------------- /images/wiki/wiki_pyrate_freecad2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/images/wiki/wiki_pyrate_freecad2.png -------------------------------------------------------------------------------- /images/wiki/wiki_pyrate_rainbow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/images/wiki/wiki_pyrate_rainbow.png -------------------------------------------------------------------------------- /docs/rtfm/graphics/waveaberrations.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/docs/rtfm/graphics/waveaberrations.jpg -------------------------------------------------------------------------------- /images/wiki/wiki_coordinate_systems.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/images/wiki/wiki_coordinate_systems.png -------------------------------------------------------------------------------- /images/wiki/wiki_pyrate_grin_opti1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/images/wiki/wiki_pyrate_grin_opti1.png -------------------------------------------------------------------------------- /images/wiki/wiki_pyrate_grin_opti2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/images/wiki/wiki_pyrate_grin_opti2.png -------------------------------------------------------------------------------- /images/wiki/wiki_pyrate_grin_opti3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/images/wiki/wiki_pyrate_grin_opti3.png -------------------------------------------------------------------------------- /images/wiki/wiki_coordinate_systems2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/images/wiki/wiki_coordinate_systems2.png -------------------------------------------------------------------------------- /images/wiki/wiki_coordinate_systems3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/images/wiki/wiki_coordinate_systems3.png -------------------------------------------------------------------------------- /images/wiki/wiki_coordinate_systems4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/images/wiki/wiki_coordinate_systems4.png -------------------------------------------------------------------------------- /images/wiki/wiki_pyrate_curved_mirrors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/images/wiki/wiki_pyrate_curved_mirrors.png -------------------------------------------------------------------------------- /images/wiki/wiki_pyrate_flat_mirrors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/images/wiki/wiki_pyrate_flat_mirrors.png -------------------------------------------------------------------------------- /pyrateoptics/raytracer/io/README.md: -------------------------------------------------------------------------------- 1 | The source files in this directory provide classes for reading and writing other formats. 2 | -------------------------------------------------------------------------------- /tests/baseline_images/smoke_test/doublet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/tests/baseline_images/smoke_test/doublet.png -------------------------------------------------------------------------------- /docs/rtfm/graphics/boundary_wavevectors_1in.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/docs/rtfm/graphics/boundary_wavevectors_1in.jpg -------------------------------------------------------------------------------- /docs/rtfm/graphics/xyuv_on_axis_astigmatism.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/docs/rtfm/graphics/xyuv_on_axis_astigmatism.png -------------------------------------------------------------------------------- /docs/rtfm/graphics/boundary_wavevectors_all8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mess42/pyrate/HEAD/docs/rtfm/graphics/boundary_wavevectors_all8.jpg -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/metadata.txt: -------------------------------------------------------------------------------- 1 | workbenches=PartWorkbench,PointsWorkbench 2 | pylibs=numpy,scipy 3 | optionalpylibs=yaml,matplotlib 4 | 5 | -------------------------------------------------------------------------------- /pyrateoptics/optimize/README.md: -------------------------------------------------------------------------------- 1 | This directory provides the optimizer functionality and necessary backends for using this functionality. 2 | 3 | -------------------------------------------------------------------------------- /run_demos: -------------------------------------------------------------------------------- 1 | for a in $(ls demos/demo*.py); do 2 | python3 -m $(echo $a | sed 's/\//./g' | sed 's/.py//g'); 3 | read -i "press any key to continue" -n 1 -t 3 4 | done 5 | -------------------------------------------------------------------------------- /pyrateoptics/raytracer/analysis/README.md: -------------------------------------------------------------------------------- 1 | Code for analysis and data output should go here. The classes here are data collecting interfaces 2 | for classes from the raytracer. 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "pyrateoptics/refractiveindex.info-database"] 2 | path = pyrateoptics/refractiveindex.info-database 3 | url = https://github.com/polyanskiy/refractiveindex.info-database.git 4 | -------------------------------------------------------------------------------- /pyrateoptics/raytracer/README.md: -------------------------------------------------------------------------------- 1 | This directory contains the physics of our project. This includes raytracing functionality, the surface 2 | and aperture descriptions and some helper functions. 3 | 4 | -------------------------------------------------------------------------------- /pyrateoptics/raytracer/material/README.md: -------------------------------------------------------------------------------- 1 | Provide materials here. Please have a look at the base class to learn which base functionalities are 2 | mandatory for implementation of a material. 3 | 4 | -------------------------------------------------------------------------------- /pyrateoptics/sampling2d/README.md: -------------------------------------------------------------------------------- 1 | This directory contains 2D grid sampling routines in the interval [-1,1]x[-1,1]. 2 | It could be used for stop and field sampling, but also for other sampling purposes. 3 | 4 | -------------------------------------------------------------------------------- /pyrateoptics/core/README.md: -------------------------------------------------------------------------------- 1 | This directory provides source files for base functionalities of our project. 2 | This includes the interface for the optimizer, the logging base functionality 3 | and serialization. 4 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include *.txt 2 | include README.md 3 | include run_demos 4 | recursive-include pyrateoptics/refractiveindex.info-database *.md *.yml 5 | recursive-include tests/baseline_images *.png 6 | recursive-include docs *.txt *.tex *.svg *.png *.jpg *.eps *.odg *.odp *.html 7 | 8 | -------------------------------------------------------------------------------- /docs/talk_euroscipy_2017/reflex_camera_cc-by-sa_anuskafm_wikipedia.txt: -------------------------------------------------------------------------------- 1 | Source: 2 | https://upload.wikimedia.org/wikipedia/commons/e/ef/Reflex_camera_%28description%29.svg 3 | 4 | Copyright holder: 5 | [[::User:Anuskafm|Anuskafm]] 6 | 7 | Licenses: 8 | GNU FDL 1.2 9 | CC-BY-SA 3.0 10 | -------------------------------------------------------------------------------- /requirements.in: -------------------------------------------------------------------------------- 1 | numpy # pyrate dependency 2 | scipy # pyrate dependency 3 | sympy # pyrate dependency 4 | matplotlib # pyrate dependency 5 | pyyaml # pyrate dependency 6 | nose2[coverage_plugin] # test automation 7 | hypothesis # quickcheck 8 | coverage # test coverage 9 | coveralls # coveralls.io CI 10 | -------------------------------------------------------------------------------- /pyrateoptics/raytracer/config/raytracer.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # provide path string, where config class generates a fully valid string from it 3 | refractive_index_path_string: ../../refractiveindex.info-database/ 4 | # is path string relative to the config file template 5 | # in Python package? 6 | refractive_index_path_is_relative: True 7 | ... 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.bak 2 | *.pyc 3 | *.aux 4 | *.bib 5 | *.dvi 6 | *.ps 7 | *.pdf 8 | *.toc 9 | *.backup 10 | *.orig 11 | *.log 12 | *.out 13 | *.bbl 14 | *.synctex.gz 15 | *.blg 16 | result_images/ 17 | .hypothesis/ 18 | 19 | # Packages 20 | *.egg 21 | *.egg-info 22 | dist 23 | build 24 | eggs 25 | parts 26 | bin 27 | var 28 | sdist 29 | develop-eggs 30 | .installed.cfg 31 | lib 32 | lib64 33 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Gui/Resources/resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | icons/pyrate_logo_icon.svg 4 | icons/pyrate_load_sys_icon.svg 5 | icons/pyrate_save_sys_icon.svg 6 | icons/pyrate_del_sys_icon.svg 7 | icons/pyrate_coord_icon.svg 8 | icons/pyrate_func_icon.svg 9 | icons/pyrate_material_icon.svg 10 | icons/pyrate_material_catalogue_icon.svg 11 | icons/pyrate_shape_icon.svg 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | # travis CI uses x64 VMs, python builds not available for OSX 4 | - "3.6" 5 | addons: 6 | apt: 7 | packages: 8 | - libblas-dev # needed for scipy/numpy 9 | - liblapack-dev # needed for scipy/numpy 10 | - gfortran # needed for scipy/numpy 11 | install: 12 | - pip install -U pip pip-tools setuptools 13 | - pip-compile # requirements.in -> requirements.txt 14 | - pip install -r requirements.in # install pyrate dependences 15 | script: 16 | - python -m nose2 --with-coverage --coverage=pyrateoptics/ tests.smoke_test 17 | after_success: 18 | - coveralls # submit test coverage information to coveralls.io 19 | 20 | -------------------------------------------------------------------------------- /freecad/Macros/test_cwov_dialog.FCMacro: -------------------------------------------------------------------------------- 1 | from pyrateoptics.core.functionobject import FunctionObject 2 | from pyrateoptics.raytracer.localcoordinates import LocalCoordinates 3 | from pyrateoptics.raytracer.surface_shape import Conic 4 | 5 | from freecad.PyrateWorkbench.TaskPanel_ClassWithOptimizableVariables_Edit import ClassWithOptimizableVariablesTaskPanelEdit 6 | 7 | 8 | lc = LocalCoordinates.p() 9 | fo = FunctionObject("f = lambda x, y: x + y", ["f"]) 10 | sh = Conic.p(lc, curv=0, cc=-1) 11 | 12 | lc.decx.set_value(1.0) 13 | lc.decy.set_value(2.0) 14 | lc.decz.to_pickup((fo, "f"), (lc.decx, lc.decy)) 15 | 16 | 17 | 18 | dlg = ClassWithOptimizableVariablesTaskPanelEdit(sh) 19 | FreeCADGui.Control.showDialog(dlg) 20 | -------------------------------------------------------------------------------- /pyrateoptics/core/names/nouns.json: -------------------------------------------------------------------------------- 1 | [ 2 | "ability", 3 | "bell", 4 | "city", 5 | "clown", 6 | "detachment", 7 | "dip", 8 | "draft", 9 | "echo", 10 | "energy", 11 | "family", 12 | "fur", 13 | "governor", 14 | "heartbeat", 15 | "heritage", 16 | "iridium", 17 | "law", 18 | "leftover", 19 | "line", 20 | "messenger", 21 | "mollusca", 22 | "nut", 23 | "orleans", 24 | "parity", 25 | "personification", 26 | "quintessence", 27 | "reference", 28 | "reformer", 29 | "semiotics", 30 | "shielding", 31 | "show", 32 | "slowdown", 33 | "specifier", 34 | "spritz", 35 | "strike", 36 | "sunstone", 37 | "surfer", 38 | "surrealism", 39 | "switch", 40 | "tracer", 41 | "undulation", 42 | "vegetable", 43 | "voice" 44 | ] -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | build: off 2 | 3 | environment: 4 | matrix: 5 | - platform: x86 6 | PYTHON_ROOT: "C:\\Python36" 7 | PYTHON_VERSION: "3.6" 8 | MINICONDA: "C:\\Miniconda" 9 | - platform: x64 10 | PYTHON_ROOT: "C:\\Python36-x64" 11 | PYTHON_VERSION: "3.6" 12 | MINICONDA: "C:\\Miniconda-x64" 13 | 14 | install: 15 | - "set PATH=%PYTHON_ROOT%;%PYTHON_ROOT%\\Scripts;%PATH%" 16 | - "set PATH=%MINICONDA%;%MINICONDA%\\Scripts;%PATH%" 17 | - conda config --set always_yes yes --set changeps1 no 18 | - conda update -q conda 19 | - "conda create -q -n test-environment python=%PYTHON_VERSION% numpy scipy matplotlib pytest" 20 | - activate test-environment 21 | - pip install -r requirements.in # install pyrate dependences 22 | 23 | test_script: 24 | - python -m nose2 tests.smoke_test # test automation, no coverage 25 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/README.md: -------------------------------------------------------------------------------- 1 | Ideas 2 | === 3 | 4 | FreeCAD Document Structure 5 | --- 6 | 7 | * Groups for 8 | * Surfaces, 9 | * Apertures, 10 | * Shapes, 11 | * Local Coordinates, 12 | * Functions, 13 | * Materials (perhaps sub groups for Shelf, Book, ... known from refractive-index.info) 14 | * No further subdivision 15 | 16 | Dialogs and UI/UX 17 | --- 18 | 19 | * Interface classes and dialogs for every ClassWithOptimizableVariables 20 | * 1:1 correspondence in a generalized manner 21 | * Changes structures/annotations of ClassWithOptimizableVariables 22 | * Links to other ClassWithOptimizableVariables if necessary 23 | 24 | * Dialogs for system creation 25 | * Dialogs for the convenience functions (tabular data) => does not need the Mirror and STOP flags 26 | * in a first step no lens editor (done by tree view in FC) 27 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Qt/lcdialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | 18 | 19 | 20 | Local coordinate systems 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Qt/dlg_functionsobject_edit.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 278 10 | 501 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | 18 | 19 | 20 | Change source code. 21 | 22 | 23 | true 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Qt/dlg_surfacelist_edit.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 297 10 | 309 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | 18 | 19 | 20 | true 21 | 22 | 23 | true 24 | 25 | 26 | 27 | Object 28 | 29 | 30 | 31 | 32 | Comment 33 | 34 | 35 | 36 | 37 | Surface 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Qt/dlg_functionsobject_add.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 278 10 | 501 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | 18 | 19 | 20 | Choose an optical system from list and type a name into the lineedit 21 | 22 | 23 | true 24 | 25 | 26 | 27 | 28 | 29 | 30 | function_object_name 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Qt/dlg_localcoords_add.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 274 10 | 182 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Choose an optical system and a parent coord system from list and type a name into the lineedit 24 | 25 | 26 | true 27 | 28 | 29 | 30 | 31 | 32 | 33 | coordsys_name 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | This CONTRIBUTION.md file is based on https://github.com/nayafia/contributing-template 2 | 3 | # Introduction 4 | 5 | First off, thank you for considering contributing to pyrate. 6 | 7 | We love to receive contributions from our community - you! 8 | There are many ways to contribute, from improving the documentation, 9 | submitting bug reports and feature requests or writing code which 10 | can be incorporated into pyrate itself. 11 | 12 | If you communicate with others be respectful and open minded. 13 | 14 | # Responsibilities 15 | 16 | For providing any contributions: 17 | 18 | * Ensure that code does not break at least the demos 19 | * Ensure that the code contributed respects the PEP8 standard (if this is not the case before your change it, file an issue) 20 | * Create issues for any major changes and enhancements that you wish to make. Discuss things transparently and get community feedback. 21 | * Keep feature versions as small as possible, preferably one new feature per version. 22 | * Be welcoming to newcomers and encourage diverse new contributors from all backgrounds. See the [Python Community Code of Conduct](https://www.python.org/psf/codeofconduct/). 23 | 24 | # When filing an issue 25 | 26 | Make sure to answer these three questions: 27 | 28 | 1. What did you do? 29 | 2. What did you expect to see? 30 | 3. What did you see instead? 31 | 32 | # Problems? 33 | 34 | Visit us on freenode (ports 6697, 7000, 7070 for SSL) channel #pyrate for some real time communication. 35 | 36 | -------------------------------------------------------------------------------- /docs/rtfm/pyrate.bib: -------------------------------------------------------------------------------- 1 | % Encoding: UTF8 2 | 3 | @BOOK{Jackson, 4 | title = {Classical Electrodynamics (Third ed.).}, 5 | publisher = {New York: Wiley}, 6 | year = {1998}, 7 | author = {John David Jackson}, 8 | isbn = {978-0-471-30932-1}, 9 | } 10 | 11 | @BOOK{BornWolf, 12 | title = {Principles of Optics (7th (expanded) ed.).}, 13 | publisher = {Cambridge: Cambridge University Press}, 14 | year = {1999}, 15 | author = {Born, Max and Wolf, Emil}, 16 | isbn = {978-0-521-64222-4}, 17 | } 18 | 19 | @ARTICLE{Forbes:2007, 20 | author = {Forbes, G. W.}, 21 | title = {Shape Specification for Axially Symmetric Optical Surfaces}, 22 | journal = {Optics Express}, 23 | year = {2007}, 24 | volume = {15}, 25 | number = {8}, 26 | pages = {5218-5226}, 27 | doi = {10.1364/OE.15.005218}, 28 | } 29 | 30 | @ARTICLE{Forbes:2010, 31 | author = {Forbes, G. W.}, 32 | title = {Robust, efficient computational methods for axially symmetric optical aspheres}, 33 | journal = {Optics Express}, 34 | year = {2010}, 35 | volume = {18}, 36 | number = {19}, 37 | pages = {19700-19712}, 38 | doi = {10.1364/OE.18.019700}, 39 | } 40 | 41 | @BOOK{Doering:1957, 42 | title = {Einf\"{u}hrung in die Theoretische Physik, Band III (Optik).}, 43 | publisher = {Berlin: Sammlung G\"{o}schen}, 44 | year = {1957}, 45 | author = {D\"{o}ring, Werner}, 46 | } 47 | 48 | @Misc{wiki:Kristalloptik, 49 | howpublished = {\url{https://de.wikipedia.org/w/index.php?title=Kristalloptik&oldid=159476511}}, 50 | note = {November 7, 2016}, 51 | title = {German Wikipedia Article: Kristalloptik}, 52 | author = {Kagawa} 53 | } 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /pyrateoptics/core/observers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env/python 2 | """ 3 | Pyrate - Optical raytracing based on Python 4 | 5 | Copyright (C) 2014-2020 6 | by Moritz Esslinger moritz.esslinger@web.de 7 | and Johannes Hartung j.hartung@gmx.net 8 | and Uwe Lippmann uwe.lippmann@web.de 9 | and Thomas Heinze t.heinze@uni-jena.de 10 | and others 11 | 12 | This program is free software; you can redistribute it and/or 13 | modify it under the terms of the GNU General Public License 14 | as published by the Free Software Foundation; either version 2 15 | of the License, or (at your option) any later version. 16 | 17 | This program is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with this program; if not, write to the Free Software 24 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 25 | """ 26 | 27 | 28 | class AbstractObserver: 29 | """ 30 | Provide observer functionality i.e. for GUI. 31 | """ 32 | def __init__(self): 33 | """ 34 | Get actualized from to be observed object. 35 | Most simple case: Observed object calls 36 | inform_about_update() 37 | """ 38 | super(AbstractObserver, self).__init__() 39 | 40 | def inform_about_update(self): 41 | """ 42 | Inform the observer about an update of the observed 43 | class. 44 | """ 45 | raise NotImplementedError() 46 | 47 | 48 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/TaskPanel_SurfaceList_Edit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import FreeCADGui 29 | 30 | from .Interface_Helpers import * 31 | from .Interface_Checks import * 32 | 33 | class SurfaceListTaskPanelEdit: 34 | def __init__(self, os): 35 | # doc needs to be initialized first 36 | self.os = os 37 | 38 | 39 | fn = getRelativeFilePath(__file__, 'Qt/dlg_surfacelist_edit.ui') 40 | 41 | 42 | # this will create a Qt widget from our ui file 43 | self.form = FreeCADGui.PySideUic.loadUi(fn) 44 | 45 | 46 | def accept(self): 47 | 48 | 49 | FreeCADGui.Control.closeDialog() 50 | -------------------------------------------------------------------------------- /pyrateoptics/core/decorators.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env/python 2 | """ 3 | Pyrate - Optical raytracing based on Python 4 | 5 | Copyright (C) 2014-2020 6 | by Moritz Esslinger moritz.esslinger@web.de 7 | and Johannes Hartung j.hartung@gmx.net 8 | and Uwe Lippmann uwe.lippmann@web.de 9 | and Thomas Heinze t.heinze@uni-jena.de 10 | and others 11 | 12 | This program is free software; you can redistribute it and/or 13 | modify it under the terms of the GNU General Public License 14 | as published by the Free Software Foundation; either version 2 15 | of the License, or (at your option) any later version. 16 | 17 | This program is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with this program; if not, write to the Free Software 24 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 25 | """ 26 | 27 | 28 | def annotate_decorator(cls): 29 | """ 30 | Class decorator based on example 4 of: 31 | https://krzysztofzuraw.com/blog/2016/python-class-decorators.html 32 | """ 33 | 34 | class AnnotateWrapper: 35 | """ 36 | Wrapper of some class. 37 | """ 38 | def __init__(self, *args, **kwargs): 39 | self.annotations = {} 40 | self.wrapped = cls(*args, **kwargs) 41 | 42 | def __getattr__(self, name): 43 | print('Getting the {} of {}'.format(name, self.wrapped)) 44 | return getattr(self.wrapped, name) 45 | 46 | return AnnotateWrapper 47 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/TaskPanel_Functions_Edit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import FreeCADGui 29 | 30 | from .Interface_Helpers import getRelativeFilePath 31 | 32 | 33 | class FunctionsTaskPanelEdit: 34 | def __init__(self, fobj): 35 | fn = getRelativeFilePath(__file__, 'Qt/dlg_functionsobject_edit.ui') 36 | 37 | # this will create a Qt widget from our ui file 38 | self.form = FreeCADGui.PySideUic.loadUi(fn) 39 | self.fobj = fobj 40 | self.form.plainTextEdit.insertPlainText( 41 | fobj.Proxy.CoreFunctionObject.source) 42 | 43 | def accept(self): 44 | self.fobj.Proxy.CoreFunctionObject.source =\ 45 | self.form.plainTextEdit.toPlainText() 46 | self.fobj.Proxy.trust() 47 | # setting to True since source code was input via text field, which 48 | # was seen by the user 49 | 50 | FreeCADGui.Control.closeDialog() 51 | -------------------------------------------------------------------------------- /pyrateoptics/raytracer/globalconstants.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import math 29 | import numpy as np 30 | 31 | # spectral lines 32 | iline = 0.3650E-3 # i (mm) 33 | hline = 0.4047E-3 # h (mm) 34 | gline = 0.4358E-3 # g (mm) 35 | Fprimeline = 0.4800E-3 # F' (mm) 36 | Fline = 0.4861E-3 # F (mm) 37 | eline = 0.5461E-3 # e (mm) 38 | dline = 0.5876E-3 # d (mm) 39 | Dline = 0.5893E-3 # D (mm) 40 | Cprimeline = 0.6438E-3 # C' (mm) 41 | Cline = 0.6563E-3 # C (mm) 42 | rline = 0.7065E-3 # r (mm) 43 | sline = 0.8521E-3 # s (mm) 44 | tline = 1.0140E-3 # t (mm) 45 | 46 | standard_wavelength = dline 47 | 48 | c0 = 299792458 # definition, m/s 49 | mu0 = 4.*math.pi*1e-7 # N/A**2 50 | eps0 = 1./(c0**2*mu0) # Vs/(Am) 51 | 52 | canonical_ex = np.array([1, 0, 0]) 53 | canonical_ey = np.array([0, 1, 0]) 54 | canonical_ez = np.array([0, 0, 1]) 55 | 56 | degree = math.pi/180.0 57 | 58 | numerical_tolerance = 1e-17 59 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Commands_Analysis.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import FreeCADGui 29 | import Part 30 | import PartGui 31 | import Points 32 | 33 | 34 | from .Observer_OpticalSystem import OpticalSystemObserver 35 | from PySide import QtGui 36 | 37 | 38 | class ShowSpotDiagramCommand: 39 | "Show spot diagram" 40 | 41 | def GetResources(self): 42 | return {"MenuText": "Spot Diagram", 43 | "Accel": "", 44 | "ToolTip": "Shows the spot diagrams for all field points", 45 | "Pixmap": ":/icons/pyrate_del_sys_icon.svg" 46 | } 47 | 48 | def IsActive(self): 49 | if FreeCAD.ActiveDocument == None: 50 | return False 51 | else: 52 | return True 53 | 54 | def Activated(self): 55 | 56 | PyrateInterface.OSinterface.showSpotDiagrams(100) 57 | 58 | 59 | FreeCADGui.addCommand('ShowSpotDiagramCommand',ShowSpotDiagramCommand()) 60 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Object_NotSerializable.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | class NotSerializable: 29 | 30 | def __getstate__(self): 31 | print(self) 32 | """ 33 | When saving the document this object gets stored using Python's 34 | json module. Since we have some un-serializable parts here 35 | -- the Coin stuff -- we must define this method 36 | to return a tuple of all serializable objects or None. 37 | 38 | Returns 39 | ------- 40 | None. 41 | 42 | """ 43 | return None 44 | 45 | def __setstate__(self, state): 46 | """ 47 | When restoring the serialized object from document we have the chance 48 | to set some internals here. Since no data were serialized nothing 49 | needs to be done here. 50 | 51 | Parameters 52 | ---------- 53 | state : TYPE 54 | DESCRIPTION. 55 | 56 | Returns 57 | ------- 58 | None. 59 | 60 | """ 61 | return None 62 | -------------------------------------------------------------------------------- /pyrateoptics/core/names/adjectives.json: -------------------------------------------------------------------------------- 1 | [ "absorbing", 2 | "accentual", 3 | "addicted", 4 | "additive", 5 | "affecting", 6 | "alien", 7 | "analytic", 8 | "anthropological", 9 | "bad", 10 | "benighted", 11 | "big", 12 | "bootlicking", 13 | "brawny", 14 | "bright", 15 | "careful", 16 | "centered", 17 | "civilized", 18 | "clawlike", 19 | "competitive", 20 | "concave", 21 | "confusing", 22 | "correlative", 23 | "covered", 24 | "deserving", 25 | "devoted", 26 | "discouraged", 27 | "easy", 28 | "empirical", 29 | "eremitic", 30 | "established", 31 | "fast", 32 | "finite", 33 | "flimsy", 34 | "fresh", 35 | "friendless", 36 | "friendly", 37 | "galilean", 38 | "generous", 39 | "heedful", 40 | "hysterical", 41 | "immaterial", 42 | "incompatible", 43 | "indelicate", 44 | "inductive", 45 | "inferior", 46 | "inflexible", 47 | "inspirational", 48 | "jealous", 49 | "laughing", 50 | "leafed", 51 | "lean", 52 | "legged", 53 | "limited", 54 | "limp", 55 | "little", 56 | "lost", 57 | "mercurial", 58 | "metaphorical", 59 | "millennial", 60 | "natural", 61 | "nonobservant", 62 | "noticeable", 63 | "oceanic", 64 | "parked", 65 | "permeant", 66 | "plutocratic", 67 | "positive", 68 | "precursory", 69 | "preliminary", 70 | "quadratic", 71 | "refined", 72 | "reflecting", 73 | "reproducible", 74 | "resolvable", 75 | "sad", 76 | "semiliterate", 77 | "sentient", 78 | "shaded", 79 | "short", 80 | "social", 81 | "sorted", 82 | "specialistic", 83 | "spinnable", 84 | "standing", 85 | "stormy", 86 | "tantalizing", 87 | "tectonic", 88 | "unanswerable", 89 | "unbodied", 90 | "unconquerable", 91 | "undeniable", 92 | "undeviating", 93 | "undue", 94 | "unstressed", 95 | "uppercase", 96 | "versatile", 97 | "washable", 98 | "wed", 99 | "yonder"] 100 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Qt/surfacedialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 773 10 | 309 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | 18 | 19 | 20 | true 21 | 22 | 23 | true 24 | 25 | 26 | 27 | Object 28 | 29 | 30 | 31 | 32 | Comment 33 | 34 | 35 | 36 | 37 | Shape 38 | 39 | 40 | 41 | 42 | Coord. System 43 | 44 | 45 | 46 | 47 | Aperture 48 | 49 | 50 | 51 | 52 | Material 53 | 54 | 55 | 56 | 57 | Conic 58 | 59 | 60 | 61 | 62 | object 63 | 64 | 65 | 66 | 67 | BaseAperture 68 | 69 | 70 | 71 | 72 | ConstantIndexGlass 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /pyrateoptics/raytracer/analysis/optical_element_analysis.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import numpy as np 29 | 30 | from ...core.log import BaseLogger 31 | 32 | 33 | class OpticalElementAnalysis(BaseLogger): 34 | """ 35 | Class for optical element analysis. 36 | """ 37 | 38 | def __init__(self, oe, elemseq, name=""): 39 | super(OpticalElementAnalysis, self).__init__(name=name) 40 | self.opticalelement = oe 41 | self.elementsequence = elemseq 42 | 43 | def setKind(self): 44 | self.kind = "opticalelementanalysis" 45 | 46 | def calc_xyuv(self, parthitlist, pilotbundle, fullsequence, 47 | background_medium): 48 | """ 49 | Calculate XYUV matrices. 50 | """ 51 | 52 | # FIXME: to many parameters in call 53 | # maybe set pilotbundle and background medium in advance 54 | 55 | (_, matrices) = self.opticalelement.\ 56 | calculateXYUV(pilotbundle, fullsequence, background_medium) 57 | 58 | tmp = np.eye(4) 59 | 60 | for hit in parthitlist: 61 | tmp = np.dot(matrices[hit], tmp) 62 | 63 | return tmp 64 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Commands_Surface.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import FreeCADGui, FreeCAD 29 | 30 | 31 | from PySide.QtGui import QLineEdit, QInputDialog 32 | 33 | from .TaskPanel_Surfaces_Add import SurfacesTaskPanelAdd 34 | 35 | from .Interface_Checks import * 36 | from .Interface_Identifiers import * 37 | 38 | 39 | class CreateSurfaceTool: 40 | "Tool for creating surface object" 41 | 42 | def GetResources(self): 43 | return {"Pixmap" : ":/icons/pyrate_shape_icon.svg", # resource qrc file needed, and precompile with python-rcc 44 | "MenuText": "Create surface ...", 45 | "Accel": "", 46 | "ToolTip": "Generates surface object in document" 47 | } 48 | 49 | def IsActive(self): 50 | if FreeCAD.ActiveDocument == None: 51 | return False 52 | else: 53 | return True 54 | 55 | def Activated(self): 56 | 57 | doc = FreeCAD.ActiveDocument 58 | 59 | 60 | panel = SurfacesTaskPanelAdd(doc) 61 | FreeCADGui.Control.showDialog(panel) 62 | 63 | 64 | FreeCADGui.addCommand('CreateSurfacesCommand', CreateSurfaceTool()) 65 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Commands_EditClassWithOptimizableVariables.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import FreeCAD, FreeCADGui 29 | from .TaskPanel_ClassWithOptimizableVariables_Edit import ClassWithOptimizableVariablesTaskPanelEdit 30 | 31 | class EditClassWithOptimizableVariablesTool: 32 | "Tool for editing class with optimizable variables object" 33 | 34 | def GetResources(self): 35 | return {"Pixmap" : ":/icons/pyrate_material_catalogue_icon.svg", # resource qrc file needed, and precompile with python-rcc 36 | "MenuText": "Edit class with optimizable variables", 37 | "Accel": "", 38 | "ToolTip": "Edit class with optimizable variable in document" 39 | } 40 | 41 | def IsActive(self): 42 | return True 43 | 44 | def Activated(self): 45 | cwov_panel = ClassWithOptimizableVariablesTaskPanelEdit(None) 46 | # wrong call (can be set to an object_reference from tree) 47 | FreeCADGui.Control.showDialog(cwov_panel) 48 | 49 | FreeCADGui.addCommand('EditClassWithOptimizableVariablesCommand', 50 | EditClassWithOptimizableVariablesTool()) 51 | 52 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Dialog_Optimization.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | from PySide import QtGui 29 | 30 | 31 | class OptimizationDialog(QtGui.QDialog): 32 | def __init__(self, iters, delta): 33 | super(OptimizationDialog, self).__init__() 34 | 35 | self.iterations = iters 36 | self.dx = delta 37 | 38 | self.initUI() 39 | 40 | def initUI(self): 41 | 42 | lbliters = QtGui.QLabel('Iterations', self) 43 | lbliters.move(10,10) 44 | 45 | self.qliters = QtGui.QLineEdit(str(self.iterations), self) 46 | self.qliters.move(10, 50) 47 | 48 | lbliters = QtGui.QLabel('dx', self) 49 | lbliters.move(10,90) 50 | 51 | self.qldx = QtGui.QLineEdit(str(self.dx), self) 52 | self.qldx.move(10, 130) 53 | 54 | okbtn = QtGui.QPushButton("OK", self) 55 | okbtn.move(10, 170) 56 | okbtn.clicked.connect(self.onOK) 57 | 58 | 59 | self.setGeometry(300, 300, 600, 500) 60 | self.setWindowTitle('Field Configuration Dialog') 61 | self.show() 62 | 63 | def onOK(self): 64 | self.iters = int(self.qliters.text()) 65 | self.dx = float(self.qldx.text()) 66 | self.close() 67 | 68 | 69 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Commands_Functions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import FreeCADGui 29 | import FreeCAD 30 | 31 | from .TaskPanel_Functions_Add import FunctionsTaskPanelAdd 32 | 33 | from .Interface_Checks import isOpticalSystemObserver 34 | 35 | 36 | class CreateFunctionTool: 37 | "Tool for creating function object" 38 | 39 | def GetResources(self): 40 | return {"Pixmap": ":/icons/pyrate_func_icon.svg", 41 | "MenuText": "Create function ...", 42 | "Accel": "", 43 | "ToolTip": "Generates function object in document" 44 | } 45 | 46 | def IsActive(self): 47 | if FreeCAD.ActiveDocument is None: 48 | return False 49 | else: 50 | return True 51 | 52 | def Activated(self): 53 | 54 | doc = FreeCAD.ActiveDocument 55 | 56 | osobservers = [] 57 | for obj in doc.Objects: 58 | if isOpticalSystemObserver(obj): 59 | osobservers.append(obj) 60 | 61 | panel = FunctionsTaskPanelAdd(doc, [oso.Label for oso in osobservers]) 62 | FreeCADGui.Control.showDialog(panel) 63 | 64 | 65 | FreeCADGui.addCommand('CreateFunctionsCommand', CreateFunctionTool()) 66 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Object_ClassWithOptimizableVariables.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | from pyrateoptics.core.base_ui import UIInterfaceClassWithOptimizableVariables 29 | 30 | from FreeCAD import newDocument 31 | 32 | 33 | class ClassWithOptimizableVariablesObject: 34 | """ 35 | FreeCAD interface object for class with optimizable variables. 36 | First of all, it should be very general. Save and Load mechanisms 37 | should be treated via the dump and read mechanism of yaml or json. 38 | (TODO: how to solve the interaction with a FreeCAD document?) 39 | """ 40 | 41 | def __init__(self, myclasswithoptimizablevariables, 42 | doc=None, super_group=None): 43 | if doc is None: 44 | self.Document = newDocument() 45 | else: 46 | self.Document = doc 47 | 48 | if super_group is None: 49 | self.SuperGroup = None 50 | else: 51 | self.SuperGroup = super_group 52 | # create subgroup in super_group or if None create group in doc 53 | # every class with optimizable variables should get one group 54 | 55 | self.Group = self.Document.addObject("App::DocumentObjectGroup", 56 | myclasswithoptimizablevariables.name) 57 | if self.SuperGroup is not None: 58 | self.SuperGroup.addObject(self.Group) 59 | -------------------------------------------------------------------------------- /pyrateoptics/core/functionobjects_pool.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | from .log import BaseLogger 29 | from .functionobject import FunctionObject 30 | 31 | 32 | class FunctionObjectsPool(BaseLogger): 33 | """ 34 | For serializing a collection of function objects 35 | """ 36 | 37 | def __init__(self, functionobjectsdictionary, name=""): 38 | super(FunctionObjectsPool, self).__init__(name=name) 39 | 40 | self.functionobjects_dictionary = functionobjectsdictionary 41 | 42 | def setKind(self): 43 | self.kind = "functionobjectspool" 44 | 45 | def to_dictionary(self): 46 | """ 47 | Save functionobjects pool in dictionary. 48 | """ 49 | result_dictionary = {} 50 | for (key, funcobj) in self.functionobjects_dictionary.items(): 51 | result_dictionary[key] = funcobj.to_dictionary() 52 | return result_dictionary 53 | 54 | @staticmethod 55 | def from_dictionary(dictionary, source_checked, variables_checked, 56 | name=""): 57 | """ 58 | Loads functionsobjects pool from dictionary. 59 | """ 60 | result_dictionary = {} 61 | for (key, fodict) in dictionary.items(): 62 | result_dictionary[key] = FunctionObject.from_dictionary( 63 | fodict, source_checked, variables_checked) 64 | return FunctionObjectsPool(result_dictionary, name=name) 65 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/TaskPanel_Functions_Add.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import FreeCADGui 29 | 30 | # from PySide import QtGui 31 | 32 | from .Object_Functions import FunctionsObject, FunctionsView 33 | 34 | from .Interface_Helpers import ( 35 | getRelativeFilePath, 36 | getOpticalSystemObservers, 37 | getFunctionObjectsSubgroupFromOpticalSystemObserver 38 | ) 39 | # from .Interface_Identifiers import Title_MessageBoxes 40 | 41 | class FunctionsTaskPanelAdd: 42 | def __init__(self, doc, stringlist): 43 | fn = getRelativeFilePath(__file__, 'Qt/dlg_functionsobject_add.ui') 44 | 45 | # this will create a Qt widget from our ui file 46 | self.form = FreeCADGui.PySideUic.loadUi(fn) 47 | self.form.comboBox.addItems(stringlist) 48 | self.doc = doc 49 | 50 | def accept(self): 51 | name_of_functionsobject = self.form.lineEditName.text() 52 | initial_source_code = self.form.plainTextEdit.toPlainText() 53 | 54 | oslabel = self.form.comboBox.currentText() 55 | oslist = getOpticalSystemObservers(self.doc, oslabel) 56 | if oslist != []: 57 | os = oslist[0] 58 | group = getFunctionObjectsSubgroupFromOpticalSystemObserver( 59 | self.doc, os) 60 | fnobj = FunctionsObject(name_of_functionsobject, initial_source_code, 61 | self.doc, 62 | group) 63 | FunctionsView(fnobj.Object.ViewObject) 64 | 65 | FreeCADGui.Control.closeDialog() 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Gui/Resources/icons/pyrate_load_sys_icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 38 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 52 | LOAD SYS 68 | 69 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Gui/Resources/icons/pyrate_save_sys_icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 38 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 52 | SAVE SYS 68 | 69 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Object_MaterialCatalogue.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | from .Interface_Identifiers import Object_MaterialCatalogue_Properties_Label 29 | from .Interface_Helpers import uuidToName 30 | 31 | 32 | import uuid 33 | 34 | from .Object_Material import MaterialObject 35 | from .Object_NotSerializable import NotSerializable 36 | 37 | class MaterialCatalogueObject(NotSerializable): 38 | 39 | 40 | def __init__(self, doc, name): 41 | self.__doc = doc # e.g. ActiveDocument 42 | self.__group = doc.addObject("App::DocumentObjectGroup", 43 | name + "_" + uuidToName(uuid.uuid4())) 44 | # materials catalogue group 45 | self.__group.Label = name 46 | 47 | self.__obj = doc.addObject("App::FeaturePython", 48 | name + 49 | Object_MaterialCatalogue_Properties_Label) 50 | self.__group.addObject(self.__obj) 51 | self.__obj.addProperty("App::PropertyStringList", 52 | "comment", # property name 53 | "Comment", # property group in task bar 54 | "comment lines").comment = [] 55 | self.__obj.addProperty("App::PropertyString", 56 | "NameMaterialsCatalogue", # property name 57 | "Comment", # property group in task bar 58 | "name of material catalogue").NameMaterialsCatalogue = self.__group.Name 59 | 60 | self.__obj.setEditorMode("NameMaterialsCatalogue", 1) # readonly 61 | 62 | 63 | self.__obj.Proxy = self 64 | # TODO: load/save 65 | 66 | def addMaterial(self, mattype, name, **kwargs): 67 | MaterialObject(self.__doc, self.__group, name, mattype, **kwargs) 68 | 69 | 70 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Qt/dlg_cwov_edit.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 487 10 | 620 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | 18 | 19 | 20 | Variables 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | true 31 | 32 | 33 | 34 | 35 | 36 | 37 | Kind 38 | 39 | 40 | 41 | 42 | 43 | 44 | true 45 | 46 | 47 | 48 | 49 | 50 | 51 | Name 52 | 53 | 54 | 55 | 56 | 57 | 58 | 3 59 | 60 | 61 | 62 | Variable 63 | 64 | 65 | 66 | 67 | Value 68 | 69 | 70 | 71 | 72 | type 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | Key 82 | 83 | 84 | 85 | 86 | Value 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | Annotations 95 | 96 | 97 | true 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Commands_FieldPoints.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import FreeCAD, FreeCADGui 29 | 30 | from .TaskPanel_FieldPoints import FieldPointsTaskPanel 31 | from .Interface_Checks import * 32 | 33 | 34 | class ShowAimDialogCommand: 35 | "Show aim dialog" 36 | 37 | def GetResources(self): 38 | return {"MenuText": "Aim Dialog", 39 | "Accel": "", 40 | "ToolTip": "You may enter data for the aiming", 41 | "Pixmap": ":/icons/pyrate_del_sys_icon.svg" 42 | } 43 | 44 | def IsActive(self): 45 | if FreeCAD.ActiveDocument == None: 46 | return False 47 | else: 48 | return True 49 | 50 | def Activated(self): 51 | pass 52 | #PyrateInterface.OSinterface.showAimFiniteSurfaceStopDialog() 53 | 54 | class ShowFieldDialogCommand: 55 | "Show field dialog" 56 | 57 | def GetResources(self): 58 | return {"MenuText": "Field Dialog", 59 | "Accel": "", 60 | "ToolTip": "You may enter field point data", 61 | "Pixmap": ":/icons/pyrate_del_sys_icon.svg" 62 | } 63 | 64 | def IsActive(self): 65 | if FreeCAD.ActiveDocument == None: 66 | return False 67 | else: 68 | selection = FreeCADGui.Selection.getSelection() 69 | if len(selection) == 1 and isOpticalSystemObserver(selection[0]): #('wavelengths' in selection[0].PropertiesList): 70 | # TODO: comparison with CheckObjects function? 71 | return True 72 | else: 73 | return False 74 | 75 | def Activated(self): 76 | osselection = FreeCADGui.Selection.getSelection()[0] # only active if len = 1 and obj is appropriate 77 | 78 | fppanel = FieldPointsTaskPanel(osselection) 79 | FreeCADGui.Control.showDialog(fppanel) 80 | 81 | 82 | FreeCADGui.addCommand('ShowAimDialogCommand',ShowAimDialogCommand()) 83 | FreeCADGui.addCommand('ShowFieldDialogCommand',ShowFieldDialogCommand()) 84 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Interface_Identifiers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Pyrate - Optical raytracing based on Python 4 | 5 | Copyright (C) 2014-2020 6 | by Moritz Esslinger moritz.esslinger@web.de 7 | and Johannes Hartung j.hartung@gmx.net 8 | and Uwe Lippmann uwe.lippmann@web.de 9 | and Thomas Heinze t.heinze@uni-jena.de 10 | and others 11 | 12 | This program is free software; you can redistribute it and/or 13 | modify it under the terms of the GNU General Public License 14 | as published by the Free Software Foundation; either version 2 15 | of the License, or (at your option) any later version. 16 | 17 | This program is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with this program; if not, write to the Free Software 24 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 25 | 26 | @author Johannes Hartung 27 | 28 | """ 29 | 30 | Title_MessageBoxes = "pyrate optics" 31 | 32 | Group_OS_Label = "Optical_System" 33 | # Label of group containing Optical System Structure 34 | Group_Functions_Label = "Functions" 35 | # Label of subgroup containing Function Objects 36 | Group_Surface_Label = "Surfaces" 37 | # Label of subgroup containing surface objects 38 | Group_Coordinates_Label = "Coordinates" 39 | # Label of subgroup containing local coordinates objects 40 | Group_StandardMaterials_Label = "StandardMaterials" 41 | # Label of global group containing standard materials (material catalogue) 42 | 43 | Object_MaterialCatalogue_Properties_Label = "_Properties" 44 | # Label of properties object in Material Catalogue 45 | 46 | Material_ConstantIndexGlass = "ConstantIndexGlass" 47 | Material_ModelGlass = "ModelGlass" 48 | Material_GrinMedium = "GrinMedium" 49 | Material_CatalogMaterial1 = "CatalogMaterial1" 50 | Material_CatalogMaterial2 = "CatalogMaterial2" 51 | Material_Mirror = "Mirror" 52 | 53 | Material_GUIChangeableProperties = ["index", "n0", "a", "b"] 54 | 55 | Material_GUI_TaskPanel_Add_TabWidget = { 56 | 0: Material_ConstantIndexGlass, 57 | 1: Material_ModelGlass, 58 | 2: Material_GrinMedium, 59 | 3: Material_CatalogMaterial1, 60 | 4: Material_CatalogMaterial2 61 | } 62 | 63 | Shape_Conic = "Conic" 64 | Shape_Cylinder = "Cylinder" 65 | Shape_Asphere = "Asphere" 66 | Shape_Explicit = "ExplicitShape" 67 | 68 | Surface_GUI_TaskPanel_Add_Shape_TabWidget = { 69 | 0: Shape_Conic, 70 | 1: Shape_Cylinder, 71 | 2: Shape_Asphere, 72 | 3: Shape_Explicit 73 | } 74 | 75 | Aperture_Base = "Base Aperture" 76 | Aperture_Circular = "Circular" 77 | Aperture_UserDefined = "User defined" 78 | 79 | Surface_GUI_TaskPanel_Add_Aperture_TabWidget = { 80 | 0: Aperture_Base, 81 | 1: Aperture_Circular, 82 | 2: Aperture_UserDefined 83 | } 84 | 85 | Surface_GUIChangeableProperties = ["curv", "cc"] # TODO: aspheric corrections 86 | Aperture_GUIChangeableProperties = ["semidiameter", "tx", "ty"] 87 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/TaskPanel_LocalCoordinates_Add.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import FreeCADGui 29 | 30 | from PySide import QtGui 31 | 32 | from .Observer_LocalCoordinates import LC 33 | 34 | from .Interface_Helpers import * 35 | from .Interface_Identifiers import * 36 | 37 | class LocalCoordinatesTaskPanelAdd: 38 | def __init__(self, doc, oslabellist): 39 | fn = getRelativeFilePath(__file__, 'Qt/dlg_localcoords_add.ui') 40 | 41 | # this will create a Qt widget from our ui file 42 | self.form = FreeCADGui.PySideUic.loadUi(fn) 43 | self.form.comboBoxOS.addItems(oslabellist) 44 | self.form.comboBoxOS.activated.connect(self.onActivatedCBOS) 45 | 46 | self.doc = doc 47 | self.actualizeLCComboBoxFromOSComboBox() 48 | 49 | 50 | def actualizeLCComboBoxFromOSComboBox(self): 51 | oslabel = self.form.comboBoxOS.currentText() 52 | oslist = self.doc.getObjectsByLabel(oslabel) 53 | if oslist != []: 54 | osselected = oslist[0] 55 | lcingroup = osselected.Proxy.returnObjectsFromCoordinatesGroup() 56 | lclabellist = [lc.Label for lc in lcingroup] 57 | self.form.comboBoxParentLC.clear() 58 | self.form.comboBoxParentLC.addItems(lclabellist) 59 | else: 60 | self.form.comboBoxParentLC.clear() 61 | 62 | 63 | def onActivatedCBOS(self, index): 64 | self.actualizeLCComboBoxFromOSComboBox() 65 | 66 | 67 | def accept(self): 68 | if self.form.comboBoxOS.currentText() != "": 69 | parentlclabel = self.form.comboBoxParentLC.currentText() 70 | name_of_newlc = self.form.lineEditName.text() 71 | parentlclist = self.doc.getObjectsByLabel(parentlclabel) 72 | if parentlclist != []: 73 | parentlc = parentlclist[0] 74 | parentlc.Proxy.addChild(name=name_of_newlc) 75 | else: 76 | pass # either warning or new global LC 77 | else: 78 | QtGui.QMessageBox.warning(None, Title_MessageBoxes, "No optical system available! Please create one.") 79 | 80 | 81 | FreeCADGui.Control.closeDialog() 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /demos/data/Thorlabs_LBF254_050_A.spd: -------------------------------------------------------------------------------- 1 | "-- Version 5.0 file --","06-15-2020" 2 | "Thorlabs LBF254-050-A","",1 3 | #FALSE# 4 | 0,#FALSE#,#FALSE#,#FALSE#,0 5 | 1,1,0,0,587.56,486.13,656.27,486.1,900 6 | "1","Stop",#TRUE#,"Nom","lens",2,"0, 0",#TRUE#,"","","","","","air"," ","","","NonSH","",0 7 | " LENS 1" 8 | " Surf 1","sphere",0,30.0599994659424,#TRUE#,"","",0,587.56,12.7,0,"","","","FALSE","FALSE|0|" 9 | " Space 1",6.5,"","N-BK7","Schott ","","","","","","","" 10 | " GlassIndex",1.51511669158936,1.5154675245285,1.51478004455566,"","" 11 | " Surf 2","sphere",0,-172,#TRUE#,"","",0,587.56,12.7,0,"","","","FALSE","FALSE|0|" 12 | " LENS 1 End" 13 | "Defocus",0,0,"" 14 | "" 15 | "Zoom",1," ",0 16 | "ObjMedia","air",""," ","ImgMedia","air",""," " 17 | "ParameterTypes",1,0,0,0,"WaveWt" 18 | 1,1,1,1,.5 19 | "Waveband",587.56,486.13,656.27,486.1,900 20 | "efl",50.2235522943853 21 | "ObjDist",-100," ImagDist",96.5574504883369 22 | "l",-100.645285456064," l'",100.249702664479 23 | "Mag",-.996069534804414," AngMag",0 24 | "Track",203.057450488337 25 | "ObjNa",.05," ImagNa",.0501973,"Stop Rad",5 26 | "entr rad",5,"exit rad",4.846923 27 | "fNos",5.022355 28 | "Entr Pup Rad",5,"Exit Pup Rad",5.065077 29 | "fNosEff",9.960695 30 | "ObjAngle",5," ObjHeight",8.74886635259239 31 | "ImagAngle",-4.936078,"ImagHeight",-8.71447923789269 32 | 0,"GaussianBeam1 1,Circ, 632.8, .8057059, .001, 805.7059, 2, .8057059, .001, 805.7059, 2,-1000, 0","","","","","","","" 33 | "Scales" 34 | "Grid",2,2,.707106,.707106,.5,100,1 35 | "GridRatio",#FALSE#,0,0 36 | "Nos colors",1,"Nos fields",2 37 | "0","0" 38 | "Nos rings",20,"Spot sepn",.3 39 | "Spot Scl",.4,"Tra Scl",.1 40 | "Opd Scl wv",.5,"OPD Scl mm",.001 41 | "Astig",.1,"Dist",1,"LatCol",.1,"Astig a",1,"LatCol a",100 42 | "Spot Scl a",100,"Tra Scl a",100 43 | "Coat",100,0,800,400,25 44 | "Max MTF",0,"Thru MTF",0,"Thru Scale",0,#FALSE# 45 | "Max MTF a",0,"Thru MTF a",0,"Thru Scale a",0 46 | "OSC",.1,"OIC",.1 47 | "RelIll Mid",.6666667,"RelIll Small",.3333333 48 | "FldMtf Mid",.6666667,"FldMtf Small",.3333333 49 | -1,-1,0,0 50 | 0,0,0,0 51 | #FALSE#,223.3632,111.1682 52 | #FALSE#,0,0,0 53 | 0,-1,0,0 54 | 400,800,632.8,.001,.8057059,805.7059,587.56,0,0,0 55 | #FALSE#,0 56 | #FALSE#,25,"","","","","","","","" 57 | "GROUPS START" 58 | " GROUP: ",1,1,1,1 59 | "GROUPS END" 60 | "Optimisation Data" 61 | "WinLens Merit Function" 62 | "VERSION B" 63 | "NOTES: " 64 | "OPTIONS START" 65 | "ModeDamp ",1 66 | "OptStrategy ",0 67 | "ModeBCViols ",0 68 | "UseDefEdgeLim ",#TRUE# 69 | "DefThickCenGap ",1,.1 70 | "DefThickEdgGap ",1,.1 71 | "DefThickCenEle ",1,.1 72 | "DefThickEdgEle ",1,.1 73 | "CtrlVariables ",#FALSE# 74 | "CtrlEdgeLims ",#TRUE# 75 | "CtrlGlassCost ",#TRUE# 76 | "Clear Aps options" 77 | "ClrApAuto ",#FALSE# 78 | "ClrApExtra ",0 79 | "ClrApRound ",0 80 | "No GCost Options" 81 | "OPTIONS END" 82 | "OPTIONS EXTRA START" 83 | "OptStratNormDoScale ",#TRUE#,0,0,"" 84 | "OptStratFindMinDamp ",#TRUE#,0,0,"" 85 | "OptEx1 ",#FALSE#,0,0,"" 86 | "OptEx2 ",#FALSE#,0,0,"" 87 | "OptEx3 ",#FALSE#,0,0,"" 88 | "OPTIONS EXTRA END" 89 | "ABERRATIONS START" 90 | " ABN: ",2,600,606,"Edge horiz","98",#FALSE#,0,1,0,1,1,1,.1,13,1,1,0,"",0,0,0,#FALSE# 91 | "ABERRATIONS END" 92 | "MF END" 93 | "" 94 | "","","","","","","","",#FALSE# 95 | #FALSE#,0 96 | "","","","","","","" 97 | "Thorlabs_LBF254_050_A.SPD" 98 | -------------------------------------------------------------------------------- /pyrateoptics/raytracer/localcoordinatestreebase.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | from ..core.base import ClassWithOptimizableVariables 29 | 30 | 31 | class LocalCoordinatesTreeBase(ClassWithOptimizableVariables): 32 | """ 33 | Optical element base class for optical system and optical element, whereas 34 | an optical system consists of many optical elements. 35 | Implements functionality for local coordinate system tree and connection 36 | checks. 37 | 38 | :param rootcoordinatesystem (LocalCoordinates object) 39 | :param name (string) 40 | :param **kwargs (key word arguments) 41 | """ 42 | @classmethod 43 | def p(cls, rootcoordinatesystem, name=""): 44 | return cls({}, {"rootcoordinatesystem": rootcoordinatesystem}, 45 | name=name) 46 | 47 | def setKind(self): 48 | self.kind = "localcoordinatestreebase" 49 | 50 | def checkForRootConnection(self, lc): 51 | """ 52 | Checks whether given local coordinate system is child of rootcoordinatesystem. 53 | 54 | :param lc (LocalCoordinates object) 55 | 56 | :return bool 57 | """ 58 | allconnectedchildren = self.rootcoordinatesystem.returnConnectedChildren() 59 | return (lc in allconnectedchildren) 60 | 61 | def addLocalCoordinateSystem(self, lc, refname): 62 | """ 63 | Adds local coordinate system as child to given reference. 64 | 65 | :param lc (LocalCoordinates object) 66 | :param refname (string) 67 | 68 | :return lc 69 | """ 70 | self.debug(lc.pprint()) 71 | allnames = self.rootcoordinatesystem.returnConnectedNames() 72 | self.debug("root coordinate system connected names: " + str(allnames)) 73 | 74 | if lc.name in allnames: 75 | # choose new name if name already in allnames 76 | lc.name = '' 77 | 78 | if refname not in allnames: 79 | # if refname is not in allnames, set it to this root 80 | refname = self.rootcoordinatesystem.name 81 | 82 | self.debug("adding child '" + lc.name + "' to reference '" + 83 | refname + "'") 84 | self.rootcoordinatesystem.addChildToReference(refname, lc) 85 | self.rootcoordinatesystem.update() 86 | 87 | return lc 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Commands_Materials.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import FreeCADGui, FreeCAD 29 | 30 | 31 | from PySide.QtGui import QLineEdit, QInputDialog 32 | 33 | from .TaskPanel_Materials_Add import MaterialsTaskPanelAdd 34 | from .Object_MaterialCatalogue import MaterialCatalogueObject 35 | 36 | from .Interface_Identifiers import Title_MessageBoxes 37 | 38 | 39 | class CreateMaterialsTool: 40 | "Tool for creating materials object" 41 | 42 | def GetResources(self): 43 | return {"Pixmap" : ":/icons/pyrate_material_icon.svg", # resource qrc file needed, and precompile with python-rcc 44 | "MenuText": "Create material ...", 45 | "Accel": "", 46 | "ToolTip": "Generates material object in document" 47 | } 48 | 49 | def IsActive(self): 50 | if FreeCAD.ActiveDocument == None: 51 | return False 52 | else: 53 | return True 54 | 55 | def Activated(self): 56 | 57 | doc = FreeCAD.ActiveDocument 58 | 59 | 60 | panel = MaterialsTaskPanelAdd(doc)#, [oso.Label for oso in osobservers]) 61 | FreeCADGui.Control.showDialog(panel) 62 | 63 | 64 | class CreateMaterialsCatalogueTool: 65 | "Tool for creating materials object" 66 | 67 | def GetResources(self): 68 | return {"Pixmap" : ":/icons/pyrate_material_catalogue_icon.svg", # resource qrc file needed, and precompile with python-rcc 69 | "MenuText": "Create material catalogue", 70 | "Accel": "", 71 | "ToolTip": "Generates material catalogue group in document" 72 | } 73 | 74 | def IsActive(self): 75 | if FreeCAD.ActiveDocument == None: 76 | return False 77 | else: 78 | return True 79 | 80 | def Activated(self): 81 | 82 | doc = FreeCAD.ActiveDocument 83 | 84 | (text, ok) = QInputDialog.getText(None, Title_MessageBoxes, 85 | "Name for material catalogue?", 86 | QLineEdit.Normal) 87 | 88 | if text and ok: 89 | MaterialCatalogueObject(doc, text) 90 | 91 | 92 | 93 | FreeCADGui.addCommand('CreateMaterialsCommand', CreateMaterialsTool()) 94 | FreeCADGui.addCommand('CreateMaterialsCatalogueCommand', CreateMaterialsCatalogueTool()) 95 | 96 | -------------------------------------------------------------------------------- /docs/rtfm/attic/eikonal_equation_approximation.tex: -------------------------------------------------------------------------------- 1 | \documentclass[a4paper,10pt]{revtex4-1} 2 | \usepackage[utf8]{inputenc} 3 | \usepackage{amsmath} 4 | 5 | %opening 6 | \title{Eikonal approximation for eigenvalue equation} 7 | 8 | \begin{document} 9 | 10 | \section{Standard evaluation} 11 | 12 | For isotropic media it follows from 13 | \begin{align} 14 | \partial_i D_i &= 0\,, 15 | \end{align} 16 | with $D_i = \varepsilon \delta_{ij} E_j = \varepsilon E_i$ that 17 | \begin{align} 18 | \partial_i E_i &= 0\,. 19 | \end{align} 20 | 21 | Further from the wave equation 22 | \begin{align} 23 | (\delta_{ij} \Delta - \partial_i \partial_j + \varepsilon \delta_{ij}) E_j &= 0 24 | \end{align} 25 | it follows the middle term can be neglected and this equation decomposes into three independent Helmholtz equations 26 | \begin{align} 27 | (\Delta + \varepsilon) E_i &= 0\,. 28 | \end{align} 29 | From the Eikonal approximation $E_i = A_i \exp(i \phi(\mathbf{x}))$ it follows that 30 | \begin{align} 31 | (\Delta + \varepsilon) \exp(i \phi) &= 0\,, 32 | \end{align} 33 | which means 34 | \begin{align} 35 | i \Delta \phi - \partial_i \phi \partial_i \phi + \varepsilon &= 0\,. 36 | \end{align} 37 | Rewriting the equation into a more convenient form leads to (with $\phi = \sqrt{\varepsilon} \phi'$) 38 | \begin{align} 39 | \partial_i \phi' \partial_i \phi' &= 1 + \frac{i}{\sqrt{\varepsilon}} \Delta \phi'\,. 40 | \end{align} 41 | For a further examination let $\phi' = \phi^\prime_0 + \frac{1}{\sqrt{\varepsilon}} \phi^\prime_1$ and neglecting higher order terms in $1/\sqrt{\varepsilon}$: 42 | \begin{align} 43 | (\partial_i \phi^\prime_0)^2 + \frac{1}{\sqrt{\varepsilon}} 2 \partial_i \phi^\prime_0 \partial_i \phi^\prime_1 &= 1 + \frac{i}{\sqrt{\varepsilon}} \Delta \phi^\prime_0\,, 44 | \end{align} 45 | leads to 46 | \begin{align} 47 | (\partial_i \phi^\prime_0)^2 &= 1\,,\\ 48 | \partial_i \phi^\prime_0 \partial_i \phi^\prime_1 &= \frac{i}{2} \Delta \phi^\prime_0\,. 49 | \end{align} 50 | Now by using this approximative scheme we can extract further information for propagation of a raybundle through an isotropic medium. 51 | Inserting the phase approximation into the divergence equation leads to: 52 | \begin{align} 53 | \partial_i E_i &= A_i \partial_i \exp(i \phi) = i A_i (\partial_i \phi) \exp(i \phi) = i E_i (\partial_i \phi) = 0\,. 54 | \end{align} 55 | This could also be used to neglect the divergence term after insertion of the phase approximation into the wave equation. 56 | 57 | 58 | \section{Anisotropic evaluation} 59 | 60 | 61 | For anisotropic media it follows from 62 | \begin{align} 63 | \partial_i D_i &= 0\,, 64 | \end{align} 65 | with $D_i = \varepsilon_{ij} E_j$ that 66 | \begin{align} 67 | \varepsilon_{ij} \partial_i E_j &= 0\,. 68 | \end{align} 69 | and therefore $i \varepsilon_{ij} (\partial_i \phi) E_j = 0$. Further from the wave equation 70 | \begin{align} 71 | (\delta_{ij} \Delta - \partial_i \partial_j + \varepsilon_{ij}) E_j &= 0 72 | \end{align} 73 | and the phase approximation $E_i = A_i \exp(i \phi)$ it is seen that 74 | \begin{align} 75 | (\delta_{ij} (i \Delta \phi - (\partial_k \phi)^2) - (i \partial_i \partial_j \phi + \partial_i \phi \partial_j \phi) + \varepsilon_{ij}) E_j &= 0 76 | \end{align} 77 | Now this equation only has non trivial solutions if the determinant of the matrix vanishes 78 | \begin{align} 79 | \det(\delta_{ij} (i \Delta \phi - (\partial_k \phi)^2) 80 | - (i \partial_i \partial_j \phi + \partial_i \phi \partial_j \phi) 81 | + \varepsilon_{ij}) &\stackrel{!}{=}0\,. 82 | \end{align} 83 | 84 | 85 | 86 | \end{document} 87 | -------------------------------------------------------------------------------- /pyrateoptics/core/names/nltk_list_generator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import sys 29 | import json 30 | import random 31 | 32 | from nltk.corpus import wordnet as wn 33 | 34 | 35 | def myinput(text, py_major_version): 36 | """ 37 | Encapsulates Python version checks for using a secure 38 | input depending on the major version. 39 | """ 40 | result = "" 41 | if py_major_version < 3: 42 | # Python2 input is insecure due to full code execution 43 | # Mitigation: raw_input 44 | result = raw_input(text) 45 | else: 46 | # Python3 input is secure 47 | result = input(text) # nosec (for bandit) 48 | return result 49 | 50 | 51 | def main(): 52 | """ 53 | Encapsulates main code. 54 | """ 55 | search_types = ["adjectives", "nouns"] 56 | wordnets = {"adjectives": wn.ADJ, "nouns": wn.NOUN} 57 | 58 | my_search_type = "" 59 | (py_major_version, _, _, _, _) = sys.version_info 60 | 61 | while my_search_type not in search_types: 62 | my_search_type = myinput( 63 | "search type? from " + str(search_types) + ": ", 64 | py_major_version 65 | ).lower() 66 | 67 | mysynsets = list(wn.all_synsets(wordnets[my_search_type])) 68 | 69 | adjectives_list = [synset.name().split(".")[0] for synset in mysynsets] 70 | 71 | try: 72 | with open(my_search_type + ".json", "rt") as filep: 73 | my_ad = json.load(filep) 74 | except IOError: 75 | my_ad = [] 76 | print("no file found, creating a new one") 77 | 78 | print(my_ad) 79 | 80 | inp = "" 81 | while inp.lower() != "q": 82 | number = random.randint(0, len(mysynsets) - 1) 83 | adjective = adjectives_list[number] 84 | if adjective not in my_ad: 85 | inp = myinput(adjective + " [y/n/q] ", py_major_version) 86 | if inp.lower() == "y": 87 | print("added") 88 | my_ad.append(adjective) 89 | else: 90 | print("rejected") 91 | 92 | my_ad = sorted(my_ad) 93 | print(my_ad) 94 | print(len(my_ad)) 95 | 96 | jsonstring = json.dumps(my_ad, ensure_ascii=True, indent=4) 97 | with open(my_search_type + ".json", "wt") as filep: 98 | filep.write(jsonstring) 99 | 100 | 101 | main() 102 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Commands_Files.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | from PySide import QtGui 29 | 30 | import FreeCAD 31 | import FreeCADGui 32 | 33 | 34 | import PyrateInterface 35 | from .Interface_Identifiers import * 36 | 37 | 38 | class LoadSystemCommand: 39 | "Load optical system file" 40 | 41 | def GetResources(self): 42 | return {"MenuText": "Load Optical System from pickle ...", 43 | "Accel": "", 44 | "ToolTip": "Loads an optical system from pickles file", 45 | "Pixmap": ":/icons/pyrate_load_sys_icon.svg" 46 | } 47 | 48 | def IsActive(self): 49 | return True 50 | 51 | def Activated(self): 52 | if FreeCAD.ActiveDocument == None: 53 | FreeCAD.newDocument() 54 | 55 | 56 | fname, _ = QtGui.QFileDialog.getOpenFileName(None, 'Open file', '') 57 | 58 | if fname == "": 59 | return 1 60 | else: 61 | pass 62 | # Loading functionality not supported, yet 63 | 64 | 65 | for i in FreeCAD.ActiveDocument.Objects: 66 | i.touch() 67 | 68 | FreeCAD.ActiveDocument.recompute() 69 | 70 | class SaveSystemCommand: 71 | "Save optical system file" 72 | 73 | def GetResources(self): 74 | return {"MenuText": "Save Optical System as pickle ...", 75 | "Accel": "", 76 | "ToolTip": "Saves an optical system to pickles file", 77 | "Pixmap": ":/icons/pyrate_save_sys_icon.svg" 78 | } 79 | 80 | def IsActive(self): 81 | if FreeCAD.ActiveDocument == None: 82 | return False 83 | else: 84 | return True 85 | 86 | def Activated(self): 87 | savedlg = QtGui.QFileDialog(None, 'Save file', '') 88 | savedlg.setFileMode(QtGui.QFileDialog.AnyFile) 89 | fname, _ = savedlg.getSaveFileName() 90 | 91 | if fname == "": 92 | return 1 93 | else: 94 | pass 95 | # Saving functionality not supported, yet 96 | # QtGui.QMessageBox.warning(None, Title_MessageBoxes, "Dumped!\n" + "Warning, pickle format may change over time!") 97 | 98 | 99 | FreeCADGui.addCommand('LoadSystemCommand',LoadSystemCommand()) 100 | FreeCADGui.addCommand('SaveSystemCommand',SaveSystemCommand()) 101 | -------------------------------------------------------------------------------- /pyrateoptics/core/base.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | from .log import BaseLogger 29 | 30 | 31 | class ClassWithOptimizableVariables(BaseLogger): 32 | """ 33 | Implementation of some class with optimizable variables with the help 34 | of a dictionary. This class is also able to collect the variables and 35 | their values from its subclasses per recursion. 36 | 37 | The goal is to provide an abstract class with pretty much functionality 38 | which gives the user the opportunity to implement a certain logic via 39 | class inheritance and interface the child class with some type of 40 | optimizer. 41 | """ 42 | def __init__(self, annotations_dict=None, 43 | structure_dict=None, name="", 44 | serializationfilter=None): 45 | """ 46 | Initialize with empty dict. 47 | 48 | :param: annotations_dict ... contains data which has to be provided 49 | :param: structure_dict ... contains structural elements (variables, 50 | subclasses) 51 | 52 | """ 53 | super(ClassWithOptimizableVariables, self).__init__(name=name) 54 | if annotations_dict is None: 55 | annotations_dict = {} 56 | if structure_dict is None: 57 | structure_dict = {} 58 | 59 | self.annotations = annotations_dict 60 | self.serializationfilter =\ 61 | [] if serializationfilter is None else serializationfilter 62 | 63 | for (key, value) in structure_dict.items(): 64 | if not hasattr(self, key): 65 | self.__setattr__(key, value) 66 | self.initialize_from_annotations() 67 | 68 | @classmethod 69 | def p(cls, **kwargs): 70 | """ 71 | Class initialization via parameters and filling up 72 | annotations and structure dictionary. To be implemented 73 | by every child class. 74 | """ 75 | name = kwargs.get("name", "") 76 | return cls({}, {}, name) 77 | 78 | def initialize_from_annotations(self): 79 | """ 80 | Further initialization stages from annotations which need to be 81 | done to get a valid object. 82 | """ 83 | pass 84 | 85 | def setKind(self): 86 | """ 87 | Set kind of object. Should be overridden in child classes. 88 | """ 89 | self.kind = "classwithoptimizablevariables" 90 | -------------------------------------------------------------------------------- /demos/demo_tilted_image.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import numpy as np 29 | 30 | from pyrateoptics import build_rotationally_symmetric_optical_system, draw 31 | from pyrateoptics.raytracer.globalconstants import degree 32 | from pyrateoptics.raytracer.analysis.optical_system_analysis import\ 33 | OpticalSystemAnalysis 34 | from pyrateoptics.raytracer.ray import RayBundle 35 | from pyrateoptics.sampling2d.raster import MeridionalFan 36 | from pyrateoptics.raytracer.helpers import build_pilotbundle_complex 37 | 38 | alpha = 10.*degree 39 | 40 | epd = 5. 41 | 42 | (s, seq) = build_rotationally_symmetric_optical_system( 43 | [(0, 0, 0., None, "object", {}), 44 | (100., 0, 5, 1.5, "lens1front", {"is_stop": True}), 45 | (0., 0, 5, None, "lens1rear", {}), 46 | (0, 0, 196.228, None, "image", {})], name="os") 47 | 48 | imsurf = s.elements["stdelem"].surfaces["image"] 49 | imsurf.rootcoordinatesystem.tiltx.set_value(alpha) 50 | imsurf.rootcoordinatesystem.update() 51 | objsurf = s.elements["stdelem"].surfaces["object"] 52 | osa = OpticalSystemAnalysis(s, seq, name="Analysis") 53 | (x01, k01, E01) = osa.collimated_bundle(11, {"radius": epd, 54 | "raster": MeridionalFan()}) 55 | (x02, k02, E02) = osa.collimated_bundle(11, {"radius": epd, 56 | "raster": MeridionalFan(), 57 | "anglex": 1.*degree}) 58 | (x03, k03, E03) = osa.collimated_bundle(11, {"radius": epd, 59 | "raster": MeridionalFan(), 60 | "anglex": -1.*degree}) 61 | 62 | mybundle1 = RayBundle(x01, k01, E01) 63 | mybundle2 = RayBundle(x02, k02, E02) 64 | mybundle3 = RayBundle(x03, k03, E03) 65 | 66 | raypaths1 = s.seqtrace(mybundle1, seq) 67 | raypaths2 = s.seqtrace(mybundle2, seq) 68 | raypaths3 = s.seqtrace(mybundle3, seq) 69 | 70 | obj_dx = 0.1 71 | obj_dphi = 0.1*degree 72 | 73 | pilotbundles = build_pilotbundle_complex(objsurf, s.material_background, 74 | (obj_dx, obj_dx), 75 | (obj_dphi, obj_dphi), 76 | num_sampling_points=3) 77 | (m_obj_stop, m_stop_img) = s.extractXYUV(pilotbundles[-1], seq) 78 | 79 | print(np.array_str(m_obj_stop, precision=5, suppress_small=True)) 80 | print(np.array_str(m_stop_img, precision=5, suppress_small=True)) 81 | 82 | draw(s, [raypaths1, raypaths2, raypaths3]) 83 | -------------------------------------------------------------------------------- /copyright_text_changer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import os 29 | 30 | """ 31 | ################################################ 32 | # The Copyright Text Changer 33 | ################################################ 34 | 35 | Opens every python file in pyrate. 36 | Cuts everything before the first import 37 | and replaces it with the copyright statement below. 38 | """ 39 | 40 | 41 | gpl_text = "\ 42 | \"\"\"\n\ 43 | Pyrate - Optical raytracing based on Python\n\ 44 | \n\ 45 | Copyright (C) 2014-2020\n\ 46 | by Moritz Esslinger moritz.esslinger@web.de\n\ 47 | and Johannes Hartung j.hartung@gmx.net\n\ 48 | and Uwe Lippmann uwe.lippmann@web.de\n\ 49 | and Thomas Heinze t.heinze@uni-jena.de\n\ 50 | and others\n\ 51 | \n\ 52 | This program is free software; you can redistribute it and/or\n\ 53 | modify it under the terms of the GNU General Public License\n\ 54 | as published by the Free Software Foundation; either version 2\n\ 55 | of the License, or (at your option) any later version.\n\ 56 | \n\ 57 | This program is distributed in the hope that it will be useful,\n\ 58 | but WITHOUT ANY WARRANTY; without even the implied warranty of\n\ 59 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\ 60 | GNU General Public License for more details.\n\ 61 | \n\ 62 | You should have received a copy of the GNU General Public License\n\ 63 | along with this program; if not, write to the Free Software\n\ 64 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n\ 65 | \"\"\"\ 66 | " 67 | 68 | for subdir, dirs, filenames in os.walk('./'): 69 | for filename in filenames: 70 | if filename.endswith(".py"): 71 | relative_filename = subdir + "/" + filename 72 | 73 | f = open(relative_filename, "r") 74 | 75 | txt = f.read() 76 | f.close 77 | 78 | a1 = txt.find("\nimport") 79 | a2 = txt.find("\nfrom ") 80 | 81 | if a1 == -1 and a2 == -1: 82 | print(relative_filename + " has no imports") 83 | else: 84 | if a1 == -1: 85 | start = a2 86 | elif a2 == -1: 87 | start = a1 88 | else: 89 | start = min(a1, a2) 90 | 91 | txt = "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n" + gpl_text + "\n" + txt[start:] 92 | 93 | f = open(relative_filename, "w") 94 | f.write(txt) 95 | f.close() 96 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Commands_Optimization.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import FreeCAD 29 | import FreeCADGui 30 | 31 | 32 | from pyrateoptics.optimize import optimize 33 | 34 | from .Observer_OpticalSystem import OpticalSystemObserver 35 | from .Dialog_Optimization import OptimizationDialog 36 | 37 | class StartOptimizationCommand: 38 | "Starts optimization" 39 | 40 | def GetResources(self): 41 | return {"MenuText": "Start Optimization", 42 | "Accel": "", 43 | "ToolTip": "Starts Optimization", 44 | "Pixmap": ":/icons/pyrate_del_sys_icon.svg" 45 | } 46 | 47 | def IsActive(self): 48 | if FreeCAD.ActiveDocument == None: 49 | return False 50 | else: 51 | return True 52 | 53 | def Activated(self): 54 | 55 | # TODO: obsolete 56 | 57 | # non-well defined interface to internal variables of optical system 58 | OSinterface.os.surfaces[2].setStatus("curvature", True) 59 | OSinterface.os.surfaces[3].setStatus("curvature", True) 60 | OSinterface.os.surfaces[4].setStatus("curvature", True) 61 | OSinterface.os.surfaces[5].setStatus("curvature", True) 62 | OSinterface.os.surfaces[7].setStatus("curvature", True) 63 | 64 | # input 65 | 66 | #numsteps_t = QtGui.QLineEdit("bla", None) # 1 67 | #dx_t = QtGui.QLineEdit("bla", None) # 1e-6 68 | 69 | #FreeCAD.Console.PrintMessage(str(numsteps_t)) 70 | 71 | optdlg = OptimizationDialog(1, 1e-6) 72 | optdlg.exec_() 73 | numsteps = optdlg.iterations 74 | delta = optdlg.dx 75 | 76 | # optimization 77 | 78 | #OSinterface.os = \ 79 | #optimize.optimizeNewton1D(OSinterface.os, 80 | # merit.mySimpleDumpRMSSpotSizeMeritFunction, iterations=numsteps, dx=delta 81 | # ) 82 | # update 83 | # TODO: organize in PyrateInterface class 84 | 85 | doc = FreeCAD.ActiveDocument 86 | 87 | OSinterface.deleteSurfaces(doc) 88 | OSinterface.deleteRays(doc) 89 | # abfrage! 90 | OSinterface.createSurfaceViews(doc) 91 | OSinterface.createRayViews(doc, OSinterface.shownumrays) 92 | 93 | 94 | for i in doc.Objects: 95 | i.touch() 96 | 97 | doc.recompute() 98 | 99 | 100 | 101 | 102 | FreeCADGui.addCommand('StartOptimizationCommand',StartOptimizationCommand()) 103 | -------------------------------------------------------------------------------- /demos/demo_benchmark.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import time 29 | import sys 30 | import logging 31 | 32 | from pyrateoptics import build_rotationally_symmetric_optical_system, draw 33 | from pyrateoptics.sampling2d import raster 34 | from pyrateoptics.raytracer.ray import RayBundle 35 | from pyrateoptics.raytracer.globalconstants import standard_wavelength, degree 36 | from pyrateoptics.raytracer.analysis.optical_system_analysis import\ 37 | OpticalSystemAnalysis 38 | 39 | from pyrateoptics.raytracer.config import ConfigFile 40 | 41 | logging.basicConfig(level=logging.INFO) 42 | 43 | wavelength = standard_wavelength 44 | 45 | # definition of optical system 46 | 47 | (s, seq) = build_rotationally_symmetric_optical_system( 48 | [(-5.922, 0, 2.0, 1.7, "surf1", {}), 49 | (-3.160, 0, 3.0, None, "surf2", {}), 50 | (15.884, 0, 5.0, 1.7, "surf3", {}), 51 | (-12.756, 0, 3.0, None, "surf4", {}), 52 | (0, 0, 3.0, None, "stop", {"is_stop": True}), 53 | (3.125, 0, 2.0, 1.5, "surf5", {}), 54 | (1.479, 0, 3.0, None, "surf6", {}), 55 | (0, 0, 19.0, None, "surf7", {}) 56 | ], material_db_path=ConfigFile().get_refractive_index_database_path()) 57 | 58 | 59 | def mytiming(): 60 | if sys.version_info.major >= 3: 61 | return time.perf_counter() 62 | else: 63 | return time.clock() 64 | 65 | 66 | nrays = 100000 67 | nrays_draw = 21 68 | 69 | osa = OpticalSystemAnalysis(s, seq, name="Analysis") 70 | 71 | (x0, k0, E0) = osa.divergent_bundle(nrays, 72 | {"radius": 10.*degree, 73 | "raster": raster.RectGrid()}) 74 | t0 = mytiming() 75 | initialraybundle = RayBundle(x0=x0, k0=k0, Efield0=E0) 76 | t1 = mytiming() 77 | raypath = s.seqtrace(initialraybundle, seq) 78 | t2 = mytiming() 79 | logging.info("benchmark : " + str(t2 - t1) + 80 | " s for tracing " + str(nrays) + " rays through " + 81 | str(len(s.elements["stdelem"].surfaces) - 1) + " surfaces.") 82 | logging.info("That is " + 83 | str(int(round(nrays * (len(s.elements["stdelem"].surfaces) - 1) 84 | / (t2 - t1)))) + 85 | " ray-surface-operations per second") 86 | 87 | # plot 88 | 89 | (x0_draw, k0_draw, E0_draw) =\ 90 | osa.divergent_bundle(nrays_draw, 91 | {"radius": 10.*degree, 92 | "raster": raster.MeridionalFan()}) 93 | initialraybundle_draw = RayBundle(x0=x0_draw, k0=k0_draw, Efield0=E0_draw) 94 | raypath_draw = s.seqtrace(initialraybundle_draw, seq) 95 | 96 | 97 | draw(s, raypath_draw) 98 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Gui/Resources/icons/pyrate_material_icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 55 | 62 | 67 | 72 | 77 | 82 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /demos/demo_optimize_goptical.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | 38 | using namespace goptical; 39 | 40 | 41 | int main(void) 42 | { 43 | 44 | material::Conrady n17(1.7, 0., 0.); 45 | material::Conrady n15(1.5, 0., 0.); 46 | 47 | shape::Disk lens_shape(2.0); // lens diameter is 2 mm 48 | 49 | sys::system mysys; 50 | 51 | sys::SourcePoint source(sys::SourceAtFiniteDistance, math::Vector3(0., 0., 0.)); 52 | 53 | sys::OpticalSurface s1(math::Vector3(0, 0, 2.0), 54 | -5.922, 2.0, material::none, n17); 55 | sys::OpticalSurface s2(math::Vector3(0, 0, 2.0 + 3.0), 56 | -3.160, 2.0, n17, material::none); 57 | sys::OpticalSurface s3(math::Vector3(0, 0, 2.0 + 3.0 + 5.0), 58 | 15.884, 2.0, material::none, n17); 59 | sys::OpticalSurface s4(math::Vector3(0, 0, 2.0 + 3.0 + 5.0 + 3.0), 60 | -12.756, 2.0, n17, material::none); 61 | sys::Stop stop(math::Vector3(0, 0, 2.0 + 3.0 + 5.0 + 3.0 + 3.0), 1.0); 62 | 63 | sys::OpticalSurface s6(math::Vector3(0, 0, 2.0 + 3.0 + 5.0 + 3.0 + 3.0 + 2.0), 64 | 3.125, 2.0, material::none, n15); 65 | sys::OpticalSurface s7(math::Vector3(0, 0, 2.0 + 3.0 + 5.0 + 3.0 + 3.0 + 2.0 + 3.0), 66 | 1.479, 2.0, n15, material::none); 67 | 68 | sys::Image image(math::Vector3(0, 0, 2.0 + 3.0 + 5.0 + 3.0 + 3.0 + 2.0 + 3.0 + 19.0), // position 69 | 10.0); // square size, 70 | 71 | mysys.add(source); 72 | mysys.add(s1); 73 | mysys.add(s2); 74 | mysys.add(s3); 75 | mysys.add(s4); 76 | mysys.add(stop); 77 | mysys.add(s6); 78 | mysys.add(s7); 79 | mysys.add(image); 80 | 81 | 82 | trace::Sequence seq(mysys); 83 | mysys.get_tracer_params().set_sequential_mode(seq); 84 | 85 | 86 | io::RendererSvg renderer("layout.svg", 1024, 100); 87 | io::RendererViewport &myrenderer = renderer; 88 | 89 | // draw 2d system layout 90 | mysys.draw_2d_fit(renderer); 91 | mysys.draw_2d(renderer); 92 | 93 | std::cout << mysys; 94 | std::cout << seq; 95 | 96 | // trace and draw rays from source 97 | 98 | std::cout << "tracer init" << std::endl; 99 | trace::tracer tracer(mysys); 100 | 101 | tracer.get_params().set_default_distribution( 102 | trace::Distribution(trace::MeridionalDist, 21.0)); 103 | tracer.get_trace_result().set_generated_save_state(source); 104 | tracer.trace(); 105 | tracer.get_trace_result().draw_2d(myrenderer); 106 | 107 | 108 | } 109 | -------------------------------------------------------------------------------- /demos/demo_asphere.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import logging 29 | 30 | import numpy as np 31 | 32 | 33 | from pyrateoptics.raytracer.ray import RayBundle 34 | from pyrateoptics.raytracer.analysis.optical_system_analysis import\ 35 | OpticalSystemAnalysis 36 | 37 | from pyrateoptics.optimize.optimize import Optimizer 38 | from pyrateoptics.optimize.optimize_backends import ScipyBackend 39 | 40 | from pyrateoptics import build_simple_optical_system, draw 41 | 42 | logging.basicConfig(level=logging.DEBUG) 43 | 44 | wavelength = 0.5876e-3 45 | 46 | # definition of optical system 47 | (s, sysseq) = build_simple_optical_system( 48 | [ 49 | ({"shape": "Conic"}, {"decz": 0.0}, None, "stop", 50 | {"is_stop": True}), 51 | ({"shape": "Conic"}, {"decz": 5.0}, 1.5168, "front", {}), 52 | ({"shape": "Asphere", "curv": -1./50., 53 | "cc": -1., "coefficients": [0.0, 0.0, 0.0]}, 54 | {"decz": 20.0}, None, "back", {}), 55 | ({"shape": "Conic"}, {"decz": 100.0}, None, "image", {}) 56 | ], 57 | ) 58 | 59 | osa = OpticalSystemAnalysis(s, sysseq, name="Analysis") 60 | 61 | (o, k, E0) = osa.collimated_bundle(121, {"startz": -5., "radius": 11.43}, 62 | wave=wavelength) 63 | initialbundle = RayBundle(x0=o, k0=k, Efield0=E0, wave=wavelength) 64 | 65 | # initialbundle = generatebundle(openangle=10.*math.pi/180, numrays=121) 66 | 67 | 68 | def meritfunctionrms(my_s): 69 | """ 70 | Standard rms spot radius merit function without removing centroid. 71 | """ 72 | initialbundle_local = RayBundle(x0=o, k0=k, Efield0=E0, wave=wavelength) 73 | rpaths = my_s.seqtrace(initialbundle_local, sysseq) 74 | # other constructions lead to fill up of initial bundle with intersection 75 | # values 76 | 77 | # for glassy asphere only one path necessary 78 | x = rpaths[0].raybundles[-1].x[-1, 0, :] 79 | y = rpaths[0].raybundles[-1].x[-1, 1, :] 80 | 81 | res = np.sum(x**2 + y**2) 82 | 83 | return res 84 | 85 | 86 | backsurf = s.elements["stdelem"].surfaces["back"] 87 | backsurf.shape.params["curv"].to_variable() 88 | backsurf.shape.params["cc"].to_variable() 89 | # A2 not variable 90 | backsurf.shape.params["A4"].to_variable() 91 | backsurf.shape.params["A6"].to_variable() 92 | 93 | opt_backend = ScipyBackend(method='Nelder-Mead', tol=1e-9) 94 | optimi = Optimizer(s, meritfunctionrms, opt_backend, 95 | name="Nelder-Mead Optimizer") 96 | s = optimi.run() 97 | 98 | r2 = s.seqtrace(initialbundle, sysseq) 99 | 100 | draw(s, r2) 101 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | from setuptools import setup 29 | 30 | long_description="""\ 31 | Pyrate - Optical Raytracing with Python 32 | ------------------------------------- 33 | 34 | Supports: 35 | - 3d arrangement of optical elements 36 | - sequential raytracing (non sequential planned) 37 | - isotropic media 38 | - anisotropic media 39 | - grin media 40 | - dispersion relations of different types 41 | - interface to refractive-index.info material data base 42 | - optimization with different optimizers 43 | 44 | Works both with Python 2.7 and Python 3.5+. 45 | """ 46 | 47 | 48 | setup( 49 | name="pyrateoptics", 50 | packages=["pyrateoptics", 51 | "tests", 52 | "pyrateoptics/core", 53 | "pyrateoptics/core/names", 54 | "pyrateoptics/raytracer", 55 | "pyrateoptics/raytracer/analysis", 56 | "pyrateoptics/raytracer/io", 57 | "pyrateoptics/sampling2d", 58 | "pyrateoptics/optimize", 59 | "pyrateoptics/raytracer/material", 60 | "demos", 61 | "freecad", 62 | "freecad/PyrateWorkbench"], 63 | package_data={"pyrateoptics/core/names": ["nouns.json", 64 | "adjectives.json"], 65 | "pyrateoptics/raytracer": ["config/raytracer.yaml"] 66 | }, 67 | include_package_data=True, 68 | install_requires=["numpy", 69 | "scipy", 70 | "matplotlib", 71 | "sympy", 72 | "pyyaml"], 73 | version="0.4.0", 74 | description="Optical raytracing with Python", 75 | author="Moritz Esslinger", 76 | author_email="moritz.esslinger@web.de", 77 | url="https://github.com/mess42/pyrate/", 78 | keywords=["optics", "raytracing"], 79 | classifiers=[ 80 | "Development Status :: 2 - Pre-Alpha", 81 | "Environment :: Console", 82 | "Intended Audience :: Developers", 83 | "Intended Audience :: Education", 84 | "Intended Audience :: Science/Research", 85 | "Intended Audience :: Manufacturing", 86 | "License :: OSI Approved :: GNU General Public License v2 (GPLv2)", 87 | "Operating System :: OS Independent", 88 | "Programming Language :: Python", 89 | "Programming Language :: Python :: 2.7", 90 | "Programming Language :: Python :: 3.5", 91 | "Programming Language :: Python :: 3.6", 92 | "Programming Language :: Python :: 3.7", 93 | "Topic :: Software Development :: Libraries :: Python Modules", 94 | "Topic :: Scientific/Engineering :: Physics" 95 | ], 96 | long_description=long_description 97 | ) 98 | -------------------------------------------------------------------------------- /demos/data/Thorlabs_AC127_050_A.spd: -------------------------------------------------------------------------------- 1 | "-- Version 5.0 file --","07-10-2020" 2 | "Thorlabs AC127-050-A","",1 3 | #FALSE# 4 | 0,#FALSE#,#FALSE#,#FALSE#,0 5 | 1,1,0,0,587.56,486.13,656.27,486.1,900 6 | "1","Stop",#TRUE#,"Nom","lens",3,"0, 0",#TRUE#,"","","","","","air"," ","","","NonSH","",0 7 | " LENS 1" 8 | " Surf 1","sphere",0,27.3999996185303,#TRUE#,"","",0,587.56,6.35,0,"","","","FALSE","FALSE|0|" 9 | " Space 1",3.5,"","N-BK7","Schott ","","","","","","","" 10 | " GlassIndex",1.51680016517639,1.522376537323,1.51432240009308,"","" 11 | " Surf 2","sphere",0,-22.5,#TRUE#,"","",0,587.56,6.35,0,"","","","FALSE","FALSE|0|" 12 | " Space 2",1.5,"","N-SF2","Schott ","","","","","","","" 13 | " GlassIndex",1.64768993854523,1.66125237941742,1.64210104942322,"","" 14 | " Surf 3","sphere",0,-91.8000030517578,#TRUE#,"","",0,587.56,6.35,0,"","","","FALSE","FALSE|0|" 15 | " LENS 1 End" 16 | "Defocus",0,0,"" 17 | "" 18 | "Zoom",1," ",0 19 | "ObjMedia","air",""," ","ImgMedia","air",""," " 20 | "ParameterTypes",1,0,0,0,"WaveWt" 21 | 1,1,1,1,.5 22 | "Waveband",587.56,486.13,656.27,486.1,900 23 | "efl",50.099827791832 24 | "ObjDist",-100," ImagDist",97.1445762282705 25 | "l",-100.469245371491," l'",99.931508708167 26 | "Mag",-.994647748558915," AngMag",0 27 | "Track",202.144576228271 28 | "ObjNa",.05," ImagNa",5.026905E-02,"Stop Rad",5 29 | "entr rad",5,"exit rad",4.883366 30 | "fNos",5.009983 31 | "Entr Pup Rad",5,"Exit Pup Rad",5.047274 32 | "fNosEff",9.946478 33 | "ObjAngle",5," ObjHeight",8.74886635259239 34 | "ImagAngle",-4.953403,"ImagHeight",-8.70204022004887 35 | 0,"GaussianBeam1 1,Circ, 632.8, .8057059, .001, 805.7059, 2, .8057059, .001, 805.7059, 2,-1000, 0","","","","","","","" 36 | "Scales" 37 | "Grid",2,2,.707106,.707106,.5,100,1 38 | "GridRatio",#FALSE#,0,0 39 | "Nos colors",1,"Nos fields",2 40 | "0","0" 41 | "Nos rings",20,"Spot sepn",.3 42 | "Spot Scl",.05,"Tra Scl",.1 43 | "Opd Scl wv",.5,"OPD Scl mm",.001 44 | "Astig",.1,"Dist",1,"LatCol",.1,"Astig a",1,"LatCol a",100 45 | "Spot Scl a",100,"Tra Scl a",100 46 | "Coat",100,0,800,400,25 47 | "Max MTF",0,"Thru MTF",0,"Thru Scale",0,#FALSE# 48 | "Max MTF a",0,"Thru MTF a",0,"Thru Scale a",0 49 | "OSC",.1,"OIC",.1 50 | "RelIll Mid",.6666667,"RelIll Small",.3333333 51 | "FldMtf Mid",.6666667,"FldMtf Small",.3333333 52 | -1,-1,-1,-1 53 | -1,-1,-1,-1 54 | #FALSE#,222.359,111.118 55 | #FALSE#,0,0,0 56 | 0,-1,-1,0 57 | 400,800,632.8,.001,.8057059,805.7059,587.56,0,0,0 58 | #FALSE#,0 59 | #FALSE#,7,"","","","","","","","" 60 | "GROUPS START" 61 | " GROUP: ",1,1,1,1 62 | "GROUPS END" 63 | "Optimisation Data" 64 | "WinLens Merit Function" 65 | "VERSION B" 66 | "NOTES: " 67 | "OPTIONS START" 68 | "ModeDamp ",1 69 | "OptStrategy ",0 70 | "ModeBCViols ",0 71 | "UseDefEdgeLim ",#TRUE# 72 | "DefThickCenGap ",1,.1 73 | "DefThickEdgGap ",1,.1 74 | "DefThickCenEle ",1,.1 75 | "DefThickEdgEle ",1,.1 76 | "CtrlVariables ",#FALSE# 77 | "CtrlEdgeLims ",#TRUE# 78 | "CtrlGlassCost ",#TRUE# 79 | "Clear Aps options" 80 | "ClrApAuto ",#FALSE# 81 | "ClrApExtra ",0 82 | "ClrApRound ",0 83 | "No GCost Options" 84 | "OPTIONS END" 85 | "OPTIONS EXTRA START" 86 | "OptStratNormDoScale ",#TRUE#,0,0,"" 87 | "OptStratFindMinDamp ",#TRUE#,0,0,"" 88 | "OptEx1 ",#FALSE#,0,0,"" 89 | "OptEx2 ",#FALSE#,0,0,"" 90 | "OptEx3 ",#FALSE#,0,0,"" 91 | "OPTIONS EXTRA END" 92 | "ABERRATIONS START" 93 | " ABN: ",2,600,606,"Edge horiz","3",#FALSE#,0,1,0,1,1,1,.1,13,1,1,0,"",0,0,0,#FALSE# 94 | " ABN: ",2,600,606,"Edge horiz","4",#FALSE#,0,1,0,2,1,1,.1,13,1,2,0,"",0,0,0,#FALSE# 95 | "ABERRATIONS END" 96 | "MF END" 97 | "" 98 | "","","","","","","","",#FALSE# 99 | #FALSE#,0 100 | "","","","","","","" 101 | "Thorlabs_AC127_050_A.SPD" 102 | -------------------------------------------------------------------------------- /demos/demo_anisotropic_mirror.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import math 29 | import logging 30 | 31 | import numpy as np 32 | 33 | from pyrateoptics.sampling2d import raster 34 | from pyrateoptics.raytracer.material.material_anisotropic import\ 35 | AnisotropicMaterial 36 | from pyrateoptics.raytracer.surface_shape import Conic 37 | from pyrateoptics.raytracer.optical_element import OpticalElement 38 | from pyrateoptics.raytracer.surface import Surface 39 | from pyrateoptics.raytracer.optical_system import OpticalSystem 40 | 41 | from pyrateoptics.raytracer.aperture import CircularAperture 42 | from pyrateoptics.raytracer.localcoordinates import LocalCoordinates 43 | from pyrateoptics.raytracer.globalconstants import degree 44 | 45 | from pyrateoptics import draw, raytrace 46 | 47 | logging.basicConfig(level=logging.DEBUG) 48 | 49 | 50 | wavelength = 0.5876e-3 51 | 52 | # definition of optical system 53 | s = OpticalSystem.p(name='os') 54 | 55 | lc0 = s.addLocalCoordinateSystem( 56 | LocalCoordinates.p(name="stop", decz=1.0), 57 | refname=s.rootcoordinatesystem.name) 58 | lc1 = s.addLocalCoordinateSystem( 59 | LocalCoordinates.p(name="surf1", decz=10.0), refname=lc0.name) 60 | lc2 = s.addLocalCoordinateSystem( 61 | LocalCoordinates.p(name="surf2", decz=5.0, tiltx=10*math.pi/180.0), 62 | refname=lc1.name) 63 | lc3 = s.addLocalCoordinateSystem( 64 | LocalCoordinates.p(name="image", decz=-5.0, tiltx=-10*math.pi/180.0), 65 | refname=lc2.name) 66 | 67 | 68 | stopsurf = Surface.p(lc0) 69 | frontsurf = Surface.p(lc1, shape=Conic.p(lc1, curv=0), 70 | aperture=CircularAperture.p(lc1, maxradius=10.0)) 71 | rearsurf = Surface.p(lc2, shape=Conic.p(lc2, curv=0), 72 | aperture=CircularAperture.p(lc3, maxradius=10.0)) 73 | image = Surface.p(lc3) 74 | 75 | 76 | elem = OpticalElement.p(lc0, name="crystalelem") 77 | 78 | no = 1.5 79 | neo = 1.8 80 | 81 | myeps = np.array([[no, 0, 0], [0, no, 0], [0, 0, neo]]) 82 | 83 | crystal = AnisotropicMaterial.p(lc1, myeps) 84 | 85 | 86 | elem.addMaterial("crystal", crystal) 87 | 88 | elem.addSurface("stop", stopsurf, (None, None)) 89 | elem.addSurface("front", frontsurf, (None, "crystal")) 90 | elem.addSurface("rear", rearsurf, ("crystal", "crystal")) 91 | elem.addSurface("image", image, ("crystal", None)) 92 | 93 | s.addElement("crystalelem", elem) 94 | 95 | sysseq = [ 96 | ("crystalelem", [ 97 | ("stop", {}), 98 | ("front", {}), 99 | ("rear", {"is_mirror": True}), 100 | ("image", {})] 101 | )] 102 | 103 | rays = raytrace(s, sysseq, 10, 104 | {"radius": 20*degree, "startz": -5., 105 | "raster": raster.MeridionalFan()}, 106 | bundletype="divergent", traceoptions={"splitup": True}, 107 | wave=wavelength) 108 | 109 | 110 | draw(s, rays) 111 | -------------------------------------------------------------------------------- /demos/demo_doublet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import logging 29 | 30 | from pyrateoptics.sampling2d import raster 31 | from pyrateoptics.raytracer.material.material_isotropic import\ 32 | ConstantIndexGlass 33 | from pyrateoptics.raytracer.surface_shape import Conic 34 | from pyrateoptics.raytracer.optical_element import OpticalElement 35 | from pyrateoptics.raytracer.surface import Surface 36 | from pyrateoptics.raytracer.optical_system import OpticalSystem 37 | 38 | from pyrateoptics.raytracer.aperture import CircularAperture 39 | from pyrateoptics.raytracer.localcoordinates import LocalCoordinates 40 | 41 | from pyrateoptics import draw, raytrace 42 | 43 | logging.basicConfig(level=logging.DEBUG) 44 | 45 | wavelength = 0.5876e-3 46 | 47 | # definition of optical system 48 | s = OpticalSystem.p() 49 | 50 | lc0 = s.addLocalCoordinateSystem( 51 | LocalCoordinates.p(name="stop", decz=0.0), 52 | refname=s.rootcoordinatesystem.name) 53 | lc1 = s.addLocalCoordinateSystem( 54 | LocalCoordinates.p(name="surf1", decz=-1.048), refname=lc0.name) 55 | # objectDist 56 | lc2 = s.addLocalCoordinateSystem( 57 | LocalCoordinates.p(name="surf2", decz=4.0), refname=lc1.name) 58 | lc3 = s.addLocalCoordinateSystem( 59 | LocalCoordinates.p(name="surf3", decz=2.5), refname=lc2.name) 60 | lc4 = s.addLocalCoordinateSystem( 61 | LocalCoordinates.p(name="image", decz=97.2), refname=lc3.name) 62 | 63 | 64 | stopsurf = Surface.p(lc0) 65 | frontsurf = Surface.p(lc1, shape=Conic.p(lc1, curv=1./62.8), 66 | aperture=CircularAperture.p(lc1, maxradius=12.7)) 67 | cementsurf = Surface.p(lc2, shape=Conic.p(lc2, curv=-1./45.7), 68 | aperture=CircularAperture.p(lc2, maxradius=12.7)) 69 | rearsurf = Surface.p(lc3, shape=Conic.p(lc3, curv=-1./128.2), 70 | aperture=CircularAperture.p(lc3, maxradius=12.7)) 71 | image = Surface.p(lc4) 72 | 73 | 74 | elem = OpticalElement.p(lc0, name="thorlabs_AC_254-100-A") 75 | 76 | bk7 = ConstantIndexGlass.p(lc1, n=1.5168) 77 | sf5 = ConstantIndexGlass.p(lc2, n=1.6727) 78 | 79 | elem.addMaterial("BK7", bk7) 80 | elem.addMaterial("SF5", sf5) 81 | 82 | elem.addSurface("stop", stopsurf, (None, None)) 83 | elem.addSurface("front", frontsurf, (None, "BK7")) 84 | elem.addSurface("cement", cementsurf, ("BK7", "SF5")) 85 | elem.addSurface("rear", rearsurf, ("SF5", None)) 86 | elem.addSurface("image", image, (None, None)) 87 | 88 | s.addElement("AC254-100", elem) 89 | 90 | sysseq = [("AC254-100", 91 | [ 92 | ("stop", {"is_stop": True}), 93 | ("front", {}), 94 | ("cement", {}), 95 | ("rear", {}), 96 | ("image", {})])] 97 | 98 | 99 | r2 = raytrace(s, sysseq, 20, 100 | {"startz": -5, "radius": 11.43, "raster": raster.MeridionalFan()}, 101 | wave=wavelength)[0] 102 | 103 | draw(s, (r2, "blue")) 104 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Qt/dlg_new_rotational_symmetric_system.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 341 10 | 529 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | Field points 21 | 22 | 23 | 24 | 25 | 26 | 27 | 0 28 | 0 29 | 30 | 31 | 32 | false 33 | 34 | 35 | Qt::ScrollBarAlwaysOn 36 | 37 | 38 | 1 39 | 40 | 41 | 6 42 | 43 | 44 | false 45 | 46 | 47 | true 48 | 49 | 50 | true 51 | 52 | 53 | 54 | 55 | Name 56 | 57 | 58 | 59 | 60 | Radius 61 | 62 | 63 | 64 | 65 | Thickness 66 | 67 | 68 | 69 | 70 | Material 71 | 72 | 73 | 74 | 75 | Mirror? 76 | 77 | 78 | 79 | 80 | Stop? 81 | 82 | 83 | 84 | 85 | Object 86 | 87 | 88 | 89 | 90 | 0 91 | 92 | 93 | 94 | 95 | 0 96 | 97 | 98 | 99 | 100 | None 101 | 102 | 103 | 104 | 105 | False 106 | 107 | 108 | 109 | 110 | False 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | Remove Surface 119 | 120 | 121 | 122 | 123 | 124 | 125 | Add Surface 126 | 127 | 128 | 129 | 130 | 131 | 132 | tblFieldPoints 133 | pbAdd 134 | pbRemove 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /demos/demo_prism.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import logging 29 | 30 | 31 | from pyrateoptics.sampling2d import raster 32 | from pyrateoptics.raytracer.material.material_isotropic import ModelGlass 33 | from pyrateoptics.raytracer.surface_shape import Conic 34 | from pyrateoptics.raytracer.optical_element import OpticalElement 35 | from pyrateoptics.raytracer.surface import Surface 36 | from pyrateoptics.raytracer.optical_system import OpticalSystem 37 | 38 | from pyrateoptics.raytracer.aperture import CircularAperture 39 | from pyrateoptics.raytracer.localcoordinates import LocalCoordinates 40 | 41 | from pyrateoptics import raytrace, draw 42 | from pyrateoptics.raytracer.globalconstants import degree 43 | 44 | logging.basicConfig(level=logging.DEBUG) 45 | 46 | wavelength = 0.5876e-3 47 | 48 | wave_red = 0.700e-3 49 | wave_blue = 0.470e-3 50 | 51 | # definition of optical system 52 | s = OpticalSystem.p() 53 | 54 | lc0 = s.addLocalCoordinateSystem( 55 | LocalCoordinates.p(name="stop", decz=0.0), 56 | refname=s.rootcoordinatesystem.name) 57 | lccomprism = s.addLocalCoordinateSystem( 58 | LocalCoordinates.p(name="prismcenter", decz=50.0), 59 | refname=lc0.name) 60 | 61 | lc1 = s.addLocalCoordinateSystem( 62 | LocalCoordinates.p(name="surf1", decz=-10.0, tiltx=30.*degree), 63 | refname=lccomprism.name) # objectDist 64 | lc2 = s.addLocalCoordinateSystem( 65 | LocalCoordinates.p(name="surf2", decz=10.0, tiltx=-30.*degree), 66 | refname=lccomprism.name) 67 | lc3 = s.addLocalCoordinateSystem( 68 | LocalCoordinates.p(name="image", decz=50.0), 69 | refname=lccomprism.name) 70 | 71 | 72 | stopsurf = Surface.p(lc0) 73 | frontsurf = Surface.p(lc1, shape=Conic.p(lc1, curv=0), 74 | aperture=CircularAperture.p(lc1, 75 | maxradius=20.0)) 76 | rearsurf = Surface.p(lc2, shape=Conic.p(lc2, curv=0), 77 | aperture=CircularAperture.p(lc2, 78 | maxradius=20.0)) 79 | image = Surface.p(lc3) 80 | 81 | 82 | elem = OpticalElement.p(lc0, name="prism") 83 | 84 | glass = ModelGlass.p(lc1) 85 | 86 | 87 | elem.addMaterial("glass", glass) 88 | 89 | elem.addSurface("stop", stopsurf, (None, None)) 90 | elem.addSurface("surf1", frontsurf, (None, "glass")) 91 | elem.addSurface("surf2", rearsurf, ("glass", None)) 92 | elem.addSurface("image", image, (None, None)) 93 | 94 | s.addElement("prism", elem) 95 | 96 | sysseq = [("prism", 97 | [("stop", {"is_stop": True}), 98 | ("surf1", {}), 99 | ("surf2", {}), 100 | ("image", {})])] 101 | 102 | raysdict = {"radius": 5.0, "startz": -5., "starty": -20., "anglex": 23*degree, 103 | "raster": raster.MeridionalFan()} 104 | 105 | r_red = raytrace(s, sysseq, 20, raysdict, wave=wave_red)[0] 106 | r_blue = raytrace(s, sysseq, 20, raysdict, wave=wave_blue)[0] 107 | 108 | 109 | draw(s, [(r_red, "red"), (r_blue, "blue")]) 110 | -------------------------------------------------------------------------------- /pyrateoptics/raytracer/analysis/surface_shape_analysis.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import numpy as np 29 | import matplotlib.pyplot as plt 30 | from ...core.log import BaseLogger 31 | 32 | 33 | class ShapeAnalysis(BaseLogger): 34 | """ 35 | Class for performing shape analysis. 36 | """ 37 | 38 | def __init__(self, shape, name=""): 39 | super(ShapeAnalysis, self).__init__(name=name) 40 | self.shape = shape 41 | 42 | def setKind(self): 43 | self.kind = "shapeanalysis" 44 | 45 | def generate_sag_table(self, xlinspace, ylinspace): 46 | """ 47 | Generates sag table (vectorial) from two linspaces. 48 | """ 49 | (xgrid, ygrid, zgrid) = self.generate_sag_matrices( 50 | xlinspace, ylinspace) 51 | xflat = xgrid.flatten() 52 | yflat = ygrid.flatten() 53 | zflat = zgrid.flatten() 54 | 55 | return np.vstack((xflat, yflat, zflat)) 56 | 57 | def generate_sag_matrices(self, xlinspace, ylinspace): 58 | """ 59 | Generates sag table (matrixvalued) from two linspaces. 60 | """ 61 | (xgrid, ygrid) = np.meshgrid(xlinspace, ylinspace) 62 | xflat = xgrid.flatten() 63 | yflat = ygrid.flatten() 64 | zflat = self.shape.getSag(xflat, yflat) 65 | zgrid = np.reshape(zflat, np.shape(xgrid)) 66 | 67 | return (xgrid, ygrid, zgrid) 68 | 69 | def load_sag_table(self, filename): 70 | """ 71 | Loads vectorial sag table. 72 | """ 73 | return np.loadtxt(filename, dtype=float).T 74 | 75 | def save_sag_table(self, filename, xlinspace, ylinspace): 76 | """ 77 | Savess vectorial sag table. 78 | """ 79 | table = self.generate_sag_table(xlinspace, ylinspace) 80 | np.savetxt(filename, table.T) 81 | 82 | def compare_with_sag_table(self, table): 83 | """ 84 | Compare sag table with function call. 85 | """ 86 | xtable = table[0] 87 | ytable = table[1] 88 | ztable = table[2] 89 | 90 | return self.shape.getSag(xtable, ytable) - ztable 91 | 92 | def plot(self, xlinspace, ylinspace, contours=10, axes=None, 93 | *args, **kwargs): 94 | """ 95 | Plots sag table to axis. 96 | """ 97 | 98 | (xgrid, ygrid, zgrid) = self.generate_sag_matrices(xlinspace, 99 | ylinspace) 100 | 101 | mask = kwargs.get('mask', np.ones_like(zgrid, dtype=bool)) 102 | zgrid[~mask] = np.nan 103 | 104 | if axes is None: 105 | plt.figure() 106 | plt.contourf(xgrid, ygrid, zgrid, contours, *args, **kwargs) 107 | plt.colorbar() 108 | plt.title(kwargs.get("title", "")) 109 | plt.show() 110 | else: 111 | axes.contourf(xgrid, ygrid, zgrid, contours, *args, **kwargs) 112 | # plt.colorbar() 113 | axes.set_title(kwargs.get("title", "")) 114 | axes.set_aspect('equal') 115 | -------------------------------------------------------------------------------- /freecad/PyrateWorkbench/Qt/dlg_optimization.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 487 10 | 538 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | 18 | 19 | 20 | QFrame::StyledPanel 21 | 22 | 23 | QFrame::Raised 24 | 25 | 26 | 27 | 28 | 29 | 1 30 | 31 | 32 | 3 33 | 34 | 35 | true 36 | 37 | 38 | 39 | 40 | Variable 41 | 42 | 43 | 44 | 45 | Status 46 | 47 | 48 | 49 | 50 | Parameters 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | Preliminary optimization dialogue. It just shows all optimizable variables in optical design. You may choose whether variable is fixed, variable, pickup or external and may run the optimizer. 62 | 63 | 64 | true 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | QFrame::StyledPanel 75 | 76 | 77 | QFrame::Raised 78 | 79 | 80 | 81 | 82 | 83 | false 84 | 85 | 86 | Qt::NoFocus 87 | 88 | 89 | true 90 | 91 | 92 | true 93 | 94 | 95 | 96 | 97 | 98 | 99 | 1 Cycle 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 10 Cycles 110 | 111 | 112 | 113 | 114 | 115 | 116 | Automatic 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /demos/demo_anisotropic_ord_eo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import logging 29 | 30 | import numpy as np 31 | 32 | from pyrateoptics.sampling2d import raster 33 | from pyrateoptics.raytracer.material.material_anisotropic import\ 34 | AnisotropicMaterial 35 | from pyrateoptics.raytracer.surface_shape import Conic 36 | from pyrateoptics.raytracer.optical_element import OpticalElement 37 | from pyrateoptics.raytracer.surface import Surface 38 | from pyrateoptics.raytracer.optical_system import OpticalSystem 39 | 40 | from pyrateoptics.raytracer.aperture import CircularAperture 41 | from pyrateoptics.raytracer.localcoordinates import LocalCoordinates 42 | from pyrateoptics.raytracer.globalconstants import degree 43 | 44 | from pyrateoptics import draw, raytrace 45 | 46 | logging.basicConfig(level=logging.DEBUG) 47 | 48 | wavelength = 0.5876e-3 49 | 50 | # definition of optical system 51 | s = OpticalSystem.p() 52 | 53 | lc0 = s.addLocalCoordinateSystem( 54 | LocalCoordinates.p(name="stop", decz=1.0), 55 | refname=s.rootcoordinatesystem.name) 56 | lc1 = s.addLocalCoordinateSystem( 57 | LocalCoordinates.p(name="surf1", decz=10.0), 58 | refname=lc0.name) # objectDist 59 | lc2 = s.addLocalCoordinateSystem( 60 | LocalCoordinates.p(name="surf2", decz=5.0), 61 | refname=lc1.name) 62 | lc3 = s.addLocalCoordinateSystem( 63 | LocalCoordinates.p(name="image", decz=10.0), 64 | refname=lc2.name) 65 | 66 | 67 | stopsurf = Surface.p(lc0) 68 | frontsurf = Surface.p(lc1, shape=Conic.p(lc1, curv=0), 69 | aperture=CircularAperture.p(lc1, maxradius=10.0)) 70 | rearsurf = Surface.p(lc2, shape=Conic.p(lc2, curv=0), 71 | aperture=CircularAperture.p(lc3, maxradius=10.0)) 72 | image = Surface.p(lc3) 73 | 74 | 75 | elem = OpticalElement.p(lc0, name="crystalelem") 76 | 77 | no = 1.5 78 | neo = 1.8 79 | 80 | myeps = np.array([[no, 0, 0], [0, no, 0], [0, 0, neo]]) 81 | 82 | crystal = AnisotropicMaterial.p(lc1, myeps) 83 | 84 | 85 | elem.addMaterial("crystal", crystal) 86 | 87 | elem.addSurface("stop", stopsurf, (None, None)) 88 | elem.addSurface("front", frontsurf, (None, "crystal")) 89 | elem.addSurface("rear", rearsurf, ("crystal", None)) 90 | elem.addSurface("image", image, (None, None)) 91 | 92 | s.addElement("crystalelem", elem) 93 | 94 | sysseq = [("crystalelem", 95 | [("stop", {"is_stop": True}), 96 | ("front", {}), 97 | ("rear", {}), 98 | ("image", {})])] 99 | 100 | 101 | raysdict = {"opticalsystem": s, "startz": -5., "radius": 20*degree, 102 | "raster": raster.MeridionalFan()} 103 | splitup = True 104 | r2 = raytrace(s, sysseq, 10, raysdict, bundletype="divergent", 105 | traceoptions={"splitup": splitup}, wave=wavelength)[0] 106 | 107 | 108 | if splitup: 109 | draw(s, [(r2[0], "blue"), (r2[1], "green")]) 110 | logging.info("contains splitted? %s" % (r2[0].containsSplitted(),)) 111 | else: 112 | draw(s, (r2[0], "blue")) 113 | logging.info(r2[0].raybundles[-1].rayID) 114 | logging.info("contains splitted? %s" % (r2[0].containsSplitted(),)) 115 | -------------------------------------------------------------------------------- /docs/rtfm/graphics/boundary_wavevectors_1in.eps: -------------------------------------------------------------------------------- 1 | %!PS-Adobe-3.0 EPSF-3.0 2 | %%Creator: cairo 1.16.0 (https://cairographics.org) 3 | %%CreationDate: Sat Jun 26 14:37:39 2021 4 | %%Pages: 1 5 | %%DocumentData: Clean7Bit 6 | %%LanguageLevel: 2 7 | %%BoundingBox: 0 0 160 107 8 | %%EndComments 9 | %%BeginProlog 10 | 50 dict begin 11 | /q { gsave } bind def 12 | /Q { grestore } bind def 13 | /cm { 6 array astore concat } bind def 14 | /w { setlinewidth } bind def 15 | /J { setlinecap } bind def 16 | /j { setlinejoin } bind def 17 | /M { setmiterlimit } bind def 18 | /d { setdash } bind def 19 | /m { moveto } bind def 20 | /l { lineto } bind def 21 | /c { curveto } bind def 22 | /h { closepath } bind def 23 | /re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto 24 | 0 exch rlineto 0 rlineto closepath } bind def 25 | /S { stroke } bind def 26 | /f { fill } bind def 27 | /f* { eofill } bind def 28 | /n { newpath } bind def 29 | /W { clip } bind def 30 | /W* { eoclip } bind def 31 | /BT { } bind def 32 | /ET { } bind def 33 | /BDC { mark 3 1 roll /BDC pdfmark } bind def 34 | /EMC { mark /EMC pdfmark } bind def 35 | /cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def 36 | /Tj { show currentpoint cairo_store_point } bind def 37 | /TJ { 38 | { 39 | dup 40 | type /stringtype eq 41 | { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse 42 | } forall 43 | currentpoint cairo_store_point 44 | } bind def 45 | /cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore 46 | cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def 47 | /Tf { pop /cairo_font exch def /cairo_font_matrix where 48 | { pop cairo_selectfont } if } bind def 49 | /Td { matrix translate cairo_font_matrix matrix concatmatrix dup 50 | /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point 51 | /cairo_font where { pop cairo_selectfont } if } bind def 52 | /Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def 53 | cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def 54 | /g { setgray } bind def 55 | /rg { setrgbcolor } bind def 56 | /d1 { setcachedevice } bind def 57 | /cairo_data_source { 58 | CairoDataIndex CairoData length lt 59 | { CairoData CairoDataIndex get /CairoDataIndex CairoDataIndex 1 add def } 60 | { () } ifelse 61 | } def 62 | /cairo_flush_ascii85_file { cairo_ascii85_file status { cairo_ascii85_file flushfile } if } def 63 | /cairo_image { image cairo_flush_ascii85_file } def 64 | /cairo_imagemask { imagemask cairo_flush_ascii85_file } def 65 | %%EndProlog 66 | %%BeginSetup 67 | %%EndSetup 68 | %%Page: 1 1 69 | %%BeginPageSetup 70 | %%PageBoundingBox: 0 0 160 107 71 | %%EndPageSetup 72 | q 0 0 160 107 rectclip 73 | 1 0 0 -1 0 108 cm q 74 | 0 0.611765 1 rg 75 | 0.309 1.727 158.832 52.531 re f 76 | 0 g 77 | 0.61984 w 78 | 1 J 79 | 0 j 80 | [] 0.0 d 81 | 4 M q 1 0 0 -1 0 0 cm 82 | 0.309 -1.727 158.832 -52.531 re S Q 83 | 0 1 1 rg 84 | 0.309 54.875 158.832 52.531 re f 85 | 0 g 86 | q 1 0 0 -1 0 0 cm 87 | 0.309 -54.875 158.832 -52.531 re S Q 88 | 2.65748 w 89 | 0 J 90 | q 1 0 0 1 0 0 cm 91 | 6.191 12.766 m 51.07 50.426 l S Q 92 | 44.555 36.562 m 53.785 52.668 l 36.32 46.379 l 40.883 45.27 44.199 41.293 93 | 44.555 36.562 c h 94 | 44.555 36.562 m f* 95 | q 1 0 0 1 0 0 cm 96 | 102.535 48.215 m 147.414 10.555 l S Q 97 | 132.633 14.562 m 150.094 8.273 l 140.867 24.379 l 140.57 19.691 137.23 98 | 15.738 132.633 14.562 c h 99 | 132.633 14.562 m f* 100 | q 1 0 0 1 0 0 cm 101 | 89.219 46.367 m 127.395 7.16 l S Q 102 | 113.09 12.637 m 129.832 4.621 l 122.27 21.574 l 121.5 16.941 117.781 13.344 103 | 113.09 12.637 c h 104 | 113.09 12.637 m f* 105 | q 1 0 0 1 0 0 cm 106 | 100.191 61.359 m 145.074 99.02 l S Q 107 | 138.559 85.156 m 147.785 101.262 l 130.32 94.973 l 134.883 93.863 138.199 108 | 89.891 138.559 85.156 c h 109 | 138.559 85.156 m f* 110 | q 1 0 0 1 0 0 cm 111 | 86.875 63.207 m 125.051 102.41 l S Q 112 | 119.961 87.965 m 127.523 104.914 l 110.781 96.902 l 115.434 96.258 119.129 113 | 92.637 119.961 87.965 c h 114 | 119.961 87.965 m f* 115 | 2.551181 w 116 | q 1 0 0 1 0 0 cm 117 | 57.426 54.699 m 94.965 54.699 l S Q 118 | 81.621 48.527 m 98.344 54.676 l 81.621 60.828 l 84.293 57.195 84.277 52.227 119 | 81.621 48.527 c h 120 | 81.621 48.527 m f* 121 | Q Q 122 | showpage 123 | %%Trailer 124 | end 125 | %%EOF 126 | -------------------------------------------------------------------------------- /tests/smoke_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | from matplotlib.testing.decorators import image_comparison 29 | from matplotlib import pyplot 30 | 31 | # we use the matplotlib's do nothing backend for testing 32 | # matplotlib/lib/matplotlib/backends/backend_template.py 33 | pyplot.switch_backend('Template') 34 | 35 | def test_smoke_anisotropic_doublet(): 36 | """Smoke test based on demo_anisotropic_doublet.py.""" 37 | import demos.demo_anisotropic_doublet 38 | assert True 39 | def test_smoke_anisotropic_mirror(): 40 | """Smoke test based on demo_anisotropic_mirror.py.""" 41 | import demos.demo_anisotropic_mirror 42 | assert True 43 | def test_smoke_anisotropic_mirrors(): 44 | """Smoke test based on demo_anisotropic_mirrors.py.""" 45 | import demos.demo_anisotropic_mirrors 46 | assert True 47 | def test_smoke_anisotropic_ord_eo(): 48 | """Smoke test based on demo_anisotropic_ord_eo.py.""" 49 | import demos.demo_anisotropic_ord_eo 50 | assert True 51 | def test_smoke_asphere(): 52 | """Smoke test based on demo_asphere.py.""" 53 | import demos.demo_asphere 54 | assert True 55 | # TODO: currently not working, due to missing refractingindex database 56 | # def test_smoke_benchmark(): 57 | # """Smoke test based on demo_benchmark.py.""" 58 | # import demos.demo_benchmark 59 | # assert True 60 | # TODO: currently not working, due to missing refractingindex database 61 | # def test_smoke_doublegauss(): 62 | # """Smoke test based on demo_doublegauss.py.""" 63 | # import demos.demo_doublegauss 64 | # assert True 65 | 66 | # TODO: decorator does not work with pytest due to different resolutions: 67 | # pytest: expects 640x480; nose: generated 800x600 68 | #@image_comparison(baseline_images=['doublet'], extensions=['png']) 69 | def test_smoke_doublet(): 70 | """Smoke test based on demo_doublet.py.""" 71 | import demos.demo_doublet 72 | assert True 73 | def test_smoke_grin(): 74 | """Smoke test based on demo_grin.py.""" 75 | import demos.demo_grin 76 | assert True 77 | def test_smoke_hud(): 78 | """Smoke test based on demo_hud.py.""" 79 | import demos.demo_hud 80 | assert True 81 | # TODO: currently not working, outdated demo script ? 82 | # def test_smoke_loadsave(): 83 | # """Smoke test based on demo_loadsave.py.""" 84 | # import demos.demo_loadsave 85 | # assert True 86 | def test_smoke_mirrors(): 87 | """Smoke test based on demo_mirrors.py.""" 88 | import demos.demo_mirrors 89 | assert True 90 | def test_smoke_optimize(): 91 | """Smoke test based on demo_optimize.py.""" 92 | import demos.demo_optimize 93 | assert True 94 | def test_smoke_prism(): 95 | """Smoke test based on demo_prism.py.""" 96 | import demos.demo_prism 97 | assert True 98 | def test_smoke_rainbow(): 99 | """Smoke test based on demo_rainbow.py.""" 100 | import demos.demo_rainbow 101 | assert True 102 | def test_smoke_zmx(): 103 | """Smoke test based on demo_zmx.py.""" 104 | import sys 105 | sys.argv = [sys.argv[0], "tests/lenssystem.ZMX", "--bundletype", "collimated", 106 | "--epd", "2.0", "--numrays", "10"] 107 | #[sys.argv[0], 'tests/lenssystem.ZMX', '10', '2'] 108 | import demos.demo_zmx 109 | assert True 110 | -------------------------------------------------------------------------------- /tests/test_ray_analysis.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import math 29 | import numpy as np 30 | from pyrateoptics.raytracer.ray import RayBundle 31 | from pyrateoptics.raytracer.analysis.ray_analysis import RayBundleAnalysis 32 | 33 | 34 | def test_centroid(): 35 | """ 36 | TODO 37 | """ 38 | raybundle = RayBundle(x0=np.array([[1, 0, 0, 1, 2], 39 | [0, 1, 0, 1, 2], 40 | [0, 0, 1, 1, 2]]), 41 | k0=np.zeros((3, 5)), Efield0=np.zeros((3, 5))) 42 | rayanalysis = RayBundleAnalysis(raybundle) 43 | centroid = rayanalysis.get_centroid_position() 44 | assert np.allclose(centroid, 4./5.) 45 | 46 | 47 | def test_rmsspotsize(): 48 | """ 49 | TODO 50 | """ 51 | raybundle = RayBundle(x0=np.array([[1, 0, 0, 1, 2], 52 | [0, 1, 0, 1, 2], 53 | [0, 0, 1, 1, 2]]), 54 | k0=np.zeros((3, 5)), Efield0=np.zeros((3, 5))) 55 | rayanalysis = RayBundleAnalysis(raybundle) 56 | rmssize = rayanalysis.get_rms_spot_size(np.array([0, 0, 0])) 57 | assert np.isclose(rmssize, math.sqrt(18.0/4.0)) 58 | 59 | 60 | def test_arc_length(): 61 | """ 62 | TODO 63 | """ 64 | k0 = np.zeros((3, 2)) 65 | E0 = np.zeros((3, 2)) 66 | raybundle = RayBundle(x0=np.array([[0, 0], [0, 0], [0, 0]]), 67 | k0=k0, Efield0=E0) 68 | x1 = np.array([[1, 0], [0, 0], [0, 0]]) 69 | x2 = np.array([[1, 1], [1, 1], [0, 0]]) 70 | x3 = np.array([[0, 2], [1, 2], [0, 0]]) 71 | x4 = np.array([[0, 3], [0, 3], [0, 0]]) 72 | valid = np.ones_like([1, 1]) 73 | raybundle.append(x1, k0, E0, valid) 74 | raybundle.append(x2, k0, E0, valid) 75 | raybundle.append(x3, k0, E0, valid) 76 | raybundle.append(x4, k0, E0, valid) 77 | arclen = RayBundleAnalysis(raybundle).get_arc_length() 78 | assert np.allclose(arclen, np.array([4., 3*np.sqrt(2)])) 79 | 80 | def test_direction_centroid(): 81 | """ 82 | TODO 83 | """ 84 | k0 = np.zeros((3, 5)) 85 | k0[2, :] = 1 86 | E0 = np.zeros((3, 5)) 87 | E0[1, :] = 1. 88 | raybundle = RayBundle(x0=np.array([[1, 0, 0, 1, 2], 89 | [0, 1, 0, 1, 2], 90 | [0, 0, 1, 1, 2]]), 91 | k0=k0, Efield0=E0) 92 | rayanalysis = RayBundleAnalysis(raybundle) 93 | centroiddir = rayanalysis.get_centroid_direction() 94 | assert np.allclose(centroiddir, np.array([0, 0, 1])) 95 | 96 | 97 | def test_rms_angularsize(): 98 | """ 99 | TODO 100 | """ 101 | k0 = np.zeros((3, 5)) 102 | k0[2, :] = 1 103 | E0 = np.zeros((3, 5)) 104 | E0[1, :] = 1. 105 | raybundle = RayBundle(x0=np.array([[1, 0, 0, 1, 2], 106 | [0, 1, 0, 1, 2], 107 | [0, 0, 1, 1, 2]]), 108 | k0=k0, Efield0=E0) 109 | rayanalysis = RayBundleAnalysis(raybundle) 110 | angularsize = rayanalysis.get_rms_angluar_size( 111 | np.array([math.sin(1.*math.pi/180.0), 0, math.cos(1.*math.pi/180.0)])) 112 | assert np.isclose(angularsize, (1.*math.pi/180.0)) 113 | -------------------------------------------------------------------------------- /tests/test_optimize.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | from pyrateoptics.core.base import ClassWithOptimizableVariables 29 | from pyrateoptics.core.optimizable_variable import (OptimizableVariable, 30 | VariableState, 31 | PickupState) 32 | from pyrateoptics.core.functionobject import FunctionObject 33 | from pyrateoptics.optimize.optimize import Optimizer 34 | from pyrateoptics.optimize.optimize_backends import (ScipyBackend, 35 | Newton1DBackend) 36 | 37 | import numpy as np 38 | 39 | 40 | def test_variables_pickups_externals(): 41 | """ 42 | Check whether pickups are also working for strings 43 | """ 44 | 45 | sum_fo = FunctionObject("f = lambda p, q: p + q", ["f"]) 46 | 47 | p = OptimizableVariable(VariableState("glass1")) 48 | q = OptimizableVariable(VariableState("glass2")) 49 | r = OptimizableVariable(PickupState((sum_fo, "f"), (p, q))) 50 | 51 | assert p() == "glass1" 52 | assert q() == "glass2" 53 | assert r() == "glass1glass2" 54 | 55 | p.set_value("glass5") 56 | q.set_value("glass6") 57 | 58 | assert r() == "glass5glass6" 59 | 60 | r._state.parameters["functionobject"] = ( 61 | FunctionObject("f = lambda x, y: x*3 + y*4", ["f"]), "f") 62 | 63 | assert r() == "glass5glass5glass5glass6glass6glass6glass6" 64 | 65 | 66 | def test_optimization(): 67 | 68 | class ExampleOS(ClassWithOptimizableVariables): 69 | def __init__(self): 70 | super(ExampleOS, self).__init__() 71 | self.X = OptimizableVariable(VariableState(3.0), name="X") 72 | self.Y = OptimizableVariable(VariableState(20.0), name="Y") 73 | self.Z = OptimizableVariable(PickupState( 74 | (FunctionObject("f = lambda x, y: x**2 + y**2", 75 | ["f"]), 76 | "f"), 77 | (self.X, self.Y)), name="Z") 78 | 79 | def testmerit(s): 80 | # let x, y being on a circle of radius 5 81 | return (s.X()**2 + s.Y()**2 - 5.**2)**2 82 | 83 | def testmerit2(s): 84 | # let x**2 + y**2 + z**2 be minimized with 85 | # the pickup constraint z = x**2 + y**2 86 | return s.X()**2 + s.Y()**2 + s.Z()**2 87 | 88 | os = ExampleOS() 89 | 90 | optimi = Optimizer(os, testmerit, 91 | backend=ScipyBackend(method="Nelder-Mead", 92 | options={"maxiter": 1000, 93 | "disp": False}, 94 | name="scipybackend"), 95 | name="optimizer") 96 | optimi.run() 97 | assert np.isclose(os.X()**2 + os.Y()**2, 25.0) 98 | optimi.meritfunction = testmerit2 99 | optimi.run() 100 | assert np.isclose(os.X()**2 + os.Y()**2, os.Z()) 101 | optimi.backend = Newton1DBackend(dx=1e-6, iterations=500) 102 | optimi.meritfunction = testmerit 103 | optimi.run() 104 | assert np.isclose(os.X()**2 + os.Y()**2, 25.0) 105 | optimi.meritfunction = testmerit2 106 | optimi.run() 107 | assert np.isclose(os.X()**2 + os.Y()**2, os.Z()) 108 | -------------------------------------------------------------------------------- /pyrateoptics/core/base_ui_transform.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | from ..raytracer.globalconstants import degree 29 | 30 | 31 | def deg2rad(deg): 32 | """ 33 | Transforms degrees in radians for UI. 34 | """ 35 | return deg*degree 36 | 37 | 38 | def rad2deg(rad): 39 | """ 40 | Transforms radians into degrees for UI. 41 | """ 42 | return rad/degree 43 | 44 | 45 | def curv2radius(curv): 46 | """ 47 | Transforms curvature to radius for UI. 48 | 1e-16 is the limit, where the radius is set to zero. 49 | """ 50 | myradius = 0. 51 | if abs(curv) > 1e-16: 52 | myradius = 1./curv 53 | return myradius 54 | 55 | 56 | def radius2curv(radius): 57 | """ 58 | Transforms radius to curvature for UI. 59 | 1e-16 is the limit, where the curvature is set to zero. 60 | """ 61 | mycurv = 0. 62 | if abs(radius) > 1e-16: 63 | mycurv = 1./radius 64 | return mycurv 65 | 66 | 67 | def radius_string(rad_string): 68 | """ 69 | Transforms radius string into a number from UI. 70 | """ 71 | result = rad_string 72 | if rad_string.lower() == "0.0" or rad_string.lower() == "0": 73 | result = "infinity" 74 | if rad_string.lower() == "inf" or\ 75 | rad_string.lower() == "oo" or\ 76 | rad_string.lower() == "infinity": 77 | result = "0.0" 78 | return result 79 | 80 | # Provides transformation dict in the form 81 | # {"kind1": {"var_name": ("shown_varname", transform_func, 82 | # inverse_transform_func), ...}, ...} 83 | # where transform_func(x) transforms the value into the written 84 | # value into UI and inverse_transform_func(x) transforms the value back 85 | # e.g.: {"shape_conic": {"curv": ("radius", lambda x: 1./x, lambda x: 1./x)}} 86 | # or: {"localcoordinates": {"tiltx": ("tiltx_deg", lambda x: x/degree, 87 | # lambda x: x*degree)}} 88 | 89 | # Translates values into human readable form. (e.g. radius better than curv, 90 | # deg better than rad) 91 | 92 | TRANSFORMATION_DICTIONARY_TO_UI =\ 93 | {"shape_Conic": {"curvature": ("radius", curv2radius)}, 94 | "shape_Cylinder": {"curvature": ("radius", curv2radius)}, 95 | "shape_Asphere": {"curv": ("radius", curv2radius)}, 96 | "shape_Biconic": {"curvx": ("radiusx", curv2radius), 97 | "curvy": ("radiusy", curv2radius)}, 98 | "localcoordinates": {"tiltx": ("tiltx_deg", rad2deg), 99 | "tilty": ("tilty_deg", rad2deg), 100 | "tiltz": ("tiltz_deg", rad2deg)}} 101 | 102 | # Translates values back into optimization friendly form. (e.g. curv better 103 | # than radius, rad better than deg.) 104 | 105 | 106 | TRANSFORMATION_DICTIONARY_FROM_UI =\ 107 | {"shape_Conic": {"radius": ("curvature", radius2curv)}, 108 | "shape_Cylinder": {"radius": ("curvature", radius2curv)}, 109 | "shape_Asphere": {"radius": ("curv", radius2curv)}, 110 | "shape_Biconic": {"radiusx": ("curvx", radius2curv), 111 | "radiusy": ("curvy", radius2curv)}, 112 | "localcoordinates": {"tiltx_deg": ("tiltx", deg2rad), 113 | "tilty_deg": ("tilty", deg2rad), 114 | "tiltz_deg": ("tiltz", deg2rad)}} 115 | 116 | # Translates converted string values into better readable/writable form. 117 | 118 | TRANSFORMATION_DICTIONARY_UI_STRING = {"radius": radius_string} 119 | -------------------------------------------------------------------------------- /pyrateoptics/raytracer/helpers_math.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import math 29 | import numpy as np 30 | 31 | 32 | def checkfinite(vec): 33 | """ 34 | Checks whether some vector vec (dim x N) is finite. If one element is not 35 | finite return False 36 | """ 37 | return np.any(np.isfinite(vec) ^ True, axis=0) ^ True 38 | 39 | 40 | def check_efield_compatibility2(efield, efield1, efield2, tol=1e-8): 41 | """ 42 | Checks whether E is in the subspace spanned by 43 | E1 and E2 by using the determinant. 44 | """ 45 | return np.abs(np.linalg.det( 46 | np.concatenate( 47 | (efield[:, np.newaxis, :], 48 | efield1[:, np.newaxis, :], 49 | efield2[:, np.newaxis, :]), axis=1).T)) < tol 50 | 51 | 52 | def check_efield_compatibility1(efield, efield1, 53 | orthogen=None, tol=1e-8): 54 | """ 55 | Check linear dependency by introducing another orthogonal vector and 56 | calculating the determinant once again. 57 | """ 58 | if orthogen is None: 59 | # Choose orthogen randomly on unit sphere 60 | orthogen = np.random.randn(*np.shape(efield)) 61 | orthogen = orthogen/np.linalg.norm(orthogen, axis=1) 62 | 63 | ortho_efield1 = orthogen -\ 64 | np.sum(orthogen*efield1, axis=0)*efield1\ 65 | /np.linalg.norm(efield1, axis=1)**2 66 | return check_efield_compatibility2(efield, efield1, ortho_efield1, tol=tol) 67 | 68 | 69 | def rodrigues(angle, axis): 70 | ''' 71 | returns numpy matrix from Rodrigues formula. 72 | 73 | @param: (float) angle in radians 74 | @param: (numpy (3x1)) axis of rotation (unit vector) 75 | 76 | @return: (numpy (3x3)) matrix of rotation 77 | ''' 78 | mat = np.array([[0, -axis[2], axis[1]], 79 | [axis[2], 0, -axis[0]], 80 | [-axis[1], axis[0], 0]]) 81 | 82 | return np.lib.eye(3) + math.sin(angle)*mat +\ 83 | (1. - math.cos(angle))*np.dot(mat, mat) 84 | 85 | 86 | def random_unitary_matrix(size): 87 | """ 88 | Generates random unitary matrix of defined size. 89 | """ 90 | rnd = np.random.randn(size*size).reshape((size, size)) +\ 91 | complex(0, 1)*np.random.randn(size*size).reshape((size, size)) 92 | (qmatrix, _) = np.linalg.qr(rnd) 93 | return qmatrix 94 | 95 | 96 | def random_unitary_matrix_sample(size, number): 97 | """ 98 | Generates random unitary matrix sample of defined size 99 | and number. 100 | """ 101 | rnd = np.random.randn(size*size).reshape((size, size, number)) +\ 102 | complex(0, 1)*np.random.randn(size*size).reshape((size, size, number)) 103 | qsamples = np.zeros_like(rnd, dtype=complex) 104 | for j in range(number): 105 | (qmatrix, _) = np.linalg.qr(rnd[:, :, j]) 106 | qsamples[:, :, j] = qmatrix 107 | return qsamples 108 | 109 | 110 | def random_rotation_matrix(size): 111 | """ 112 | Generates random rotation matrix of defined size. 113 | """ 114 | rnd = np.random.randn(size*size).reshape((size, size)) 115 | (qmatrix, _) = np.linalg.qr(rnd) 116 | return qmatrix 117 | 118 | 119 | def random_rotation_matrix_sample(size, number): 120 | """ 121 | Generates random rotation matrix sample of defined size and 122 | number 123 | """ 124 | rnd = np.random.randn(size*size).reshape((size, size, number)) 125 | qsamples = np.zeros_like(rnd) 126 | for j in range(number): 127 | (qmatrix, _) = np.linalg.qr(rnd[:, :, j]) 128 | qsamples[:, :, j] = qmatrix 129 | return qsamples 130 | -------------------------------------------------------------------------------- /pyrateoptics/optimize/optimize.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | from ..core.log import BaseLogger 29 | from ..core.iterators import OptimizableVariableActiveCollector 30 | 31 | 32 | class Optimizer(BaseLogger): 33 | ''' 34 | Easy optimization interface. All variables are public such that a quick 35 | attachment of other meritfunctions or other update functions with other 36 | parameters is possible. 37 | ''' 38 | def __init__(self, classwithoptvariables, 39 | meritfunction, backend, 40 | name="", updatefunction=None): 41 | super(Optimizer, self).__init__(name=name) 42 | 43 | def noupdate(_): 44 | "No update dummy callback function" 45 | pass 46 | 47 | self.collector = OptimizableVariableActiveCollector( 48 | classwithoptvariables) 49 | self.meritfunction = meritfunction # function to minimize 50 | if updatefunction is None: 51 | updatefunction = noupdate 52 | self.updatefunction = updatefunction 53 | # function to be called to update classwithoptvariables 54 | self.set_backend(backend) 55 | # eats vector performs optimization, returns vector 56 | # scipy Nelder-Mead, scipy ..., evolutionary, genetic, ... 57 | 58 | self.meritparameters = {} 59 | self.updateparameters = {} 60 | self.number_of_calls = 0 61 | # how often is the merit function called during one run? 62 | 63 | def setKind(self): 64 | self.kind = "optimizer" 65 | 66 | def set_backend(self, backend): 67 | "Setter for backend." 68 | self.__backend = backend 69 | self.__backend.init(self.meritfunction_wrapper) 70 | 71 | backend = property(fget=None, fset=set_backend) 72 | 73 | def meritfunction_wrapper(self, vecx): 74 | """ 75 | Merit function wrapper for backend. 76 | Notice that vecx and length of active values must have the same size 77 | 78 | :param vecx (np.array): active variable values 79 | :param meritfunction (function): meritfunction depending on s 80 | 81 | :return value of the merit function 82 | """ 83 | self.number_of_calls += 1 84 | self.collector.fromNumpyArrayTransformed(vecx) 85 | self.updatefunction(self.collector.class_instance, 86 | **self.updateparameters) 87 | res = self.meritfunction(self.collector.class_instance, 88 | **self.meritparameters) 89 | self.debug("call number " + str(self.number_of_calls) + 90 | " meritfunction: " + str(res)) 91 | return res 92 | 93 | def run(self): 94 | ''' 95 | Funtion to perform a certain number of optimization steps. 96 | ''' 97 | self.info("optimizer run start") 98 | vecx0 = self.collector.toNumpyArrayTransformed() 99 | 100 | self.info("initial x: " + str(vecx0)) 101 | self.info("initial merit: " + str(self.meritfunction_wrapper(vecx0))) 102 | self.debug("calling backend run") 103 | xfinal = self.__backend.run(vecx0) 104 | self.debug("finished backend run") 105 | self.info("final x: " + str(xfinal)) 106 | self.info("final merit: " + str(self.meritfunction_wrapper(xfinal))) 107 | self.collector.fromNumpyArrayTransformed(xfinal) 108 | self.info("called merit function " + str(self.number_of_calls) + 109 | " times.") 110 | self.number_of_calls = 0 111 | self.info("optimizer run finished") 112 | return self.collector.class_instance 113 | -------------------------------------------------------------------------------- /docs/rtfm/attic/anisotropic_formulae.tex: -------------------------------------------------------------------------------- 1 | \documentclass[a4paper,12pt]{article} 2 | \usepackage[utf8]{inputenc} 3 | \usepackage{amsmath} 4 | \usepackage{amssymb} 5 | \usepackage{dsfont} 6 | 7 | %opening 8 | \title{Anisotropic Media Formulas from ``Landau Lifschitz -- Elektrodynamik der Kontinua''} 9 | 10 | \newcommand{\vct}[1]{{\bf #1}} 11 | 12 | \begin{document} 13 | 14 | \maketitle 15 | 16 | All units are in cgs. (TODO: convert to SI.) 17 | 18 | \section{Energy dissipation (paragraph 96)} 19 | \begin{align} 20 | Q &= \frac{i \omega}{16 \pi} 21 | \left[ 22 | (\varepsilon^\ast_{ik} - \varepsilon_{ki})E_i E_k^\ast 23 | + (\mu^\ast_{ik} - \mu_{ki})H_i H_k^\ast 24 | \right]\,. 25 | \end{align} 26 | 27 | Useful either at every surface or in grin media at 28 | every integration point. 29 | 30 | \section{Formal plane wave (paragraph 83)} 31 | \begin{align} 32 | \exp(i \vct{k} \vct{r}) &= \exp(i \vct{k}^\prime \vct{r}) 33 | \exp(-\vct{k}^{\prime\prime} \vct{r})\,, 34 | \end{align} 35 | where $\vct{k} = \vct{k}^\prime + i \vct{k}^{\prime\prime}$. 36 | 37 | \section{Eikonal (paragraph 85)} 38 | 39 | \begin{align} 40 | \phi &= a \exp(i \psi)\,,\\ 41 | \frac{\partial \psi}{\partial t} &= -\omega\,,\quad 42 | \vct{\nabla} \psi = \vct{k}\,,\\ 43 | \psi &= -\omega t + \frac{\omega}{c} \psi_1(x, y, z)\,. 44 | \end{align} 45 | From this it is: 46 | \begin{align} 47 | \vct{\nabla}\psi_1 &= \vct{n}\text{ with }\vct{k} = \frac{\omega}{c}\vct{n}\,. 48 | \end{align} 49 | Therefore: 50 | \begin{align} 51 | \psi_1 &= \int_A^B \vct{n}\text{d}\vct{l} \stackrel{\text{isotropic}}{=} \int_A^B n \text{d}l\,. 52 | \end{align} 53 | (For isotropic: $\vct{n}$ points in direction of $\text{d}\vct{l}$ 54 | and $\vct{n}^2 = n^2$ is the square of the refractive index.) 55 | 56 | \section{Poynting Vector (paragraph 85)} 57 | Represents the ray direction in optics. 58 | \begin{align} 59 | \bar{\vct{S}} &= I \vct{l}\text{ and }\vct{\nabla}(I \vct{l}) = 0\,.\\ 60 | \bar{\vct{S}} &= \mathfrak{R} 61 | \left( 62 | \frac{c}{4\pi} \frac{1}{2} 63 | \vct{E} \times \vct{H}^\ast 64 | \right)\,. 65 | \end{align} 66 | Also group $\tfrac{\partial \omega}{\partial \vct{k}}$ 67 | velocity represents ray direction. 68 | 69 | \section{Dispersion for k (paragraph 97)} 70 | 71 | \begin{align} 72 | (n^2 \delta_{ik} - n_i n_k - \varepsilon_{ik}) E_k &= 0\,,\\ 73 | f(\vct{k}, \omega) = \det(n^2 \delta_{ik} - n_i n_k - \varepsilon_{ik}) &= 0\,. 74 | \end{align} 75 | 76 | \section{Introducing ray vector s (paragraph 97)} 77 | 78 | Direction fixed by Poynting vector or group velocity. 79 | 80 | \begin{align} 81 | \vct{s} &\sim \bar{\vct{S}} \sim \frac{\partial \omega}{\partial \vct{k}}\,. 82 | \end{align} 83 | 84 | Group velocity given by: 85 | \begin{align} 86 | \frac{\partial \omega}{\partial \vct{k}} &= - 87 | \frac{\frac{\partial f}{\partial \vct{k}}} 88 | {\frac{\partial f}{\partial \omega}}\,. 89 | \end{align} 90 | 91 | 92 | Introduction into Eikonal 93 | 94 | \begin{align} 95 | \psi_1 &= \int_A^B \vct{n} \text{d}\vct{l} 96 | = \int_A^B \vct{n}\cdot\frac{\vct{s}}{s} \text{d}l\,. 97 | \end{align} 98 | 99 | Absolute value is fixed by demanding that 100 | \begin{align} 101 | \vct{n}\cdot\vct{s} &= 1\,, 102 | \end{align} 103 | such that 104 | \begin{align} 105 | \psi_1 &= \int_A^B \frac{\text{d}l}{s}\,. 106 | \end{align} 107 | 108 | \section{Dual Dispersion for s (paragraph 97)} 109 | 110 | \begin{align} 111 | \det(s^2 \delta_{ik} - s_i s_k - (\varepsilon^{-1})_{ik}) &= 0\,. 112 | \end{align} 113 | 114 | Notice, this works also for complex valued $\varepsilon_{ij}$. $\vct{s}$ is then also complex valued 115 | but points in the direction of $\bar{\vct{S}}$. 116 | 117 | \section{Fermats principle and anisotropic media} 118 | 119 | Let $\psi_1$ be real and demand that $\psi_1$ is minimal along the path the wave travels, 120 | \begin{align} 121 | \psi_1 &= \int_A^B \vct{n}(\vct{x}) \text{d} \vct{x} = \text{min}\,. 122 | \end{align} 123 | Then the Lagrangian after introduction of a curve parameter $\tau$ is given by 124 | \begin{align} 125 | L &= \vct{n}(\vct{x}(\tau)) \frac{\text{d}\vct{x}}{\text{d}\tau} = n_\ell \dot{x}_\ell\,. 126 | \end{align} 127 | Then 128 | \begin{align} 129 | \frac{\partial L}{\partial x_k} &= (\partial_k n_\ell) \dot{x}_\ell\,,\\ 130 | p_k = \frac{\partial L}{\partial \dot{x}_k} &= n_\ell \delta_{\ell k} = n_k\,. 131 | \end{align} 132 | Therefore 133 | \begin{align} 134 | \frac{\partial L}{\partial x_k} - \frac{\text{d}}{\text{d}\tau}\frac{\partial L}{\partial \dot{x}_k} &= 0\,, 135 | \end{align} 136 | leads to 137 | \begin{align} 138 | (\partial_k n_\ell) \dot{x}_\ell - \frac{\text{d} n_k}{\text{d} \tau} &= 0\,. 139 | \end{align} 140 | This can further be simplified to 141 | \begin{align} 142 | [(\partial_k n_\ell) - (\partial_\ell n_k)] \dot{x}_\ell &= 0\,. 143 | \end{align} 144 | 145 | 146 | 147 | \end{document} 148 | -------------------------------------------------------------------------------- /docs/rtfm/graphics/boundary_wavevectors_all8.eps: -------------------------------------------------------------------------------- 1 | %!PS-Adobe-3.0 EPSF-3.0 2 | %%Creator: cairo 1.16.0 (https://cairographics.org) 3 | %%CreationDate: Sat Jun 26 14:37:55 2021 4 | %%Pages: 1 5 | %%DocumentData: Clean7Bit 6 | %%LanguageLevel: 2 7 | %%BoundingBox: 0 0 160 107 8 | %%EndComments 9 | %%BeginProlog 10 | 50 dict begin 11 | /q { gsave } bind def 12 | /Q { grestore } bind def 13 | /cm { 6 array astore concat } bind def 14 | /w { setlinewidth } bind def 15 | /J { setlinecap } bind def 16 | /j { setlinejoin } bind def 17 | /M { setmiterlimit } bind def 18 | /d { setdash } bind def 19 | /m { moveto } bind def 20 | /l { lineto } bind def 21 | /c { curveto } bind def 22 | /h { closepath } bind def 23 | /re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto 24 | 0 exch rlineto 0 rlineto closepath } bind def 25 | /S { stroke } bind def 26 | /f { fill } bind def 27 | /f* { eofill } bind def 28 | /n { newpath } bind def 29 | /W { clip } bind def 30 | /W* { eoclip } bind def 31 | /BT { } bind def 32 | /ET { } bind def 33 | /BDC { mark 3 1 roll /BDC pdfmark } bind def 34 | /EMC { mark /EMC pdfmark } bind def 35 | /cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def 36 | /Tj { show currentpoint cairo_store_point } bind def 37 | /TJ { 38 | { 39 | dup 40 | type /stringtype eq 41 | { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse 42 | } forall 43 | currentpoint cairo_store_point 44 | } bind def 45 | /cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore 46 | cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def 47 | /Tf { pop /cairo_font exch def /cairo_font_matrix where 48 | { pop cairo_selectfont } if } bind def 49 | /Td { matrix translate cairo_font_matrix matrix concatmatrix dup 50 | /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point 51 | /cairo_font where { pop cairo_selectfont } if } bind def 52 | /Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def 53 | cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def 54 | /g { setgray } bind def 55 | /rg { setrgbcolor } bind def 56 | /d1 { setcachedevice } bind def 57 | /cairo_data_source { 58 | CairoDataIndex CairoData length lt 59 | { CairoData CairoDataIndex get /CairoDataIndex CairoDataIndex 1 add def } 60 | { () } ifelse 61 | } def 62 | /cairo_flush_ascii85_file { cairo_ascii85_file status { cairo_ascii85_file flushfile } if } def 63 | /cairo_image { image cairo_flush_ascii85_file } def 64 | /cairo_imagemask { imagemask cairo_flush_ascii85_file } def 65 | %%EndProlog 66 | %%BeginSetup 67 | %%EndSetup 68 | %%Page: 1 1 69 | %%BeginPageSetup 70 | %%PageBoundingBox: 0 0 160 107 71 | %%EndPageSetup 72 | q 0 0 160 107 rectclip 73 | 1 0 0 -1 0 108 cm q 74 | 0 0.611765 1 rg 75 | 0.309 1.727 158.832 52.531 re f 76 | 0 g 77 | 0.61984 w 78 | 1 J 79 | 0 j 80 | [] 0.0 d 81 | 4 M q 1 0 0 -1 0 0 cm 82 | 0.309 -1.727 158.832 -52.531 re S Q 83 | 0 1 1 rg 84 | 0.309 54.875 158.832 52.531 re f 85 | 0 g 86 | q 1 0 0 -1 0 0 cm 87 | 0.309 -54.875 158.832 -52.531 re S Q 88 | 2.65748 w 89 | 0 J 90 | q 1 0 0 1 0 0 cm 91 | 6.191 12.766 m 51.07 50.426 l S Q 92 | 44.555 36.562 m 53.785 52.668 l 36.32 46.379 l 40.883 45.27 44.199 41.293 93 | 44.555 36.562 c h 94 | 44.555 36.562 m f* 95 | q 1 0 0 1 0 0 cm 96 | 27.957 5.84 m 66.129 45.047 l S Q 97 | 61.039 30.602 m 68.605 47.551 l 51.859 39.539 l 56.512 38.895 60.207 35.273 98 | 61.039 30.602 c h 99 | 61.039 30.602 m f* 100 | q 1 0 0 1 0 0 cm 101 | 102.535 48.215 m 147.414 10.555 l S Q 102 | 132.633 14.562 m 150.094 8.273 l 140.867 24.379 l 140.57 19.691 137.23 103 | 15.738 132.633 14.562 c h 104 | 132.633 14.562 m f* 105 | q 1 0 0 1 0 0 cm 106 | 89.219 46.367 m 127.395 7.16 l S Q 107 | 113.09 12.637 m 129.832 4.621 l 122.27 21.574 l 121.5 16.941 117.781 13.344 108 | 113.09 12.637 c h 109 | 113.09 12.637 m f* 110 | q 1 0 0 1 0 0 cm 111 | 3.848 96.809 m 48.727 59.148 l S Q 112 | 33.945 63.156 m 51.406 56.867 l 42.18 72.973 l 41.883 68.285 38.543 64.332 113 | 33.945 63.156 c h 114 | 33.945 63.156 m f* 115 | q 1 0 0 1 0 0 cm 116 | 25.613 103.73 m 63.785 64.527 l S Q 117 | 49.48 70 m 66.223 61.988 l 58.66 78.938 l 57.891 74.305 54.172 70.707 49.48 118 | 70 c h 119 | 49.48 70 m f* 120 | q 1 0 0 1 0 0 cm 121 | 100.191 61.359 m 145.074 99.02 l S Q 122 | 138.559 85.156 m 147.785 101.262 l 130.32 94.973 l 134.883 93.863 138.199 123 | 89.891 138.559 85.156 c h 124 | 138.559 85.156 m f* 125 | q 1 0 0 1 0 0 cm 126 | 86.875 63.207 m 125.051 102.41 l S Q 127 | 119.961 87.965 m 127.523 104.914 l 110.781 96.902 l 115.434 96.258 119.129 128 | 92.637 119.961 87.965 c h 129 | 119.961 87.965 m f* 130 | 2.551181 w 131 | q 1 0 0 1 0 0 cm 132 | 57.426 54.699 m 94.965 54.699 l S Q 133 | 81.621 48.527 m 98.344 54.676 l 81.621 60.828 l 84.293 57.195 84.277 52.227 134 | 81.621 48.527 c h 135 | 81.621 48.527 m f* 136 | Q Q 137 | showpage 138 | %%Trailer 139 | end 140 | %%EOF 141 | -------------------------------------------------------------------------------- /demos/demo_zmx.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Pyrate - Optical raytracing based on Python 5 | 6 | Copyright (C) 2014-2020 7 | by Moritz Esslinger moritz.esslinger@web.de 8 | and Johannes Hartung j.hartung@gmx.net 9 | and Uwe Lippmann uwe.lippmann@web.de 10 | and Thomas Heinze t.heinze@uni-jena.de 11 | and others 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version 2 16 | of the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | GNU General Public License for more details. 22 | 23 | You should have received a copy of the GNU General Public License 24 | along with this program; if not, write to the Free Software 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | """ 27 | 28 | import sys 29 | import logging 30 | import argparse 31 | 32 | import matplotlib.pyplot as plt 33 | 34 | 35 | from pyrateoptics.raytracer.localcoordinates import LocalCoordinates 36 | from pyrateoptics.raytracer.material.material_isotropic import\ 37 | ConstantIndexGlass 38 | from pyrateoptics.raytracer.globalconstants import standard_wavelength 39 | from pyrateoptics.raytracer.io.zmx import ZMXParser 40 | 41 | from pyrateoptics.sampling2d import raster 42 | from pyrateoptics import draw 43 | 44 | from pyrateoptics.raytracer.analysis.optical_system_analysis import\ 45 | OpticalSystemAnalysis 46 | 47 | 48 | logging.basicConfig(level=logging.DEBUG) 49 | 50 | # download ZMX files from e.g.: 51 | # http://astro.dur.ac.uk/~rsharp/opticaldesign/ 52 | # some good demonstration of coordinate breaks is: FIELDROTATOR-LECT5.ZMX 53 | 54 | parser = argparse.ArgumentParser(description="Read ZMX files.") 55 | parser.add_argument("file", help="File to be interpreted", 56 | type=str) 57 | parser.add_argument("--bundletype", nargs='?', help="Bundle type", 58 | type=str, default='collimated') 59 | parser.add_argument("--epd", nargs='?', help="Entrance pupil diameter", 60 | type=float, default=1.0) 61 | parser.add_argument("--numrays", nargs='?', help="Number of rays", 62 | type=int, default=11) 63 | parser.add_argument("--showspot", help="Show spot diagram?", 64 | action="store_true") 65 | parser.add_argument("--anglex", help="Angle", type=float, default=0.0) 66 | parser.add_argument("--reverse", help="Send light in reverse direction?", 67 | action="store_true") 68 | parser.add_argument("--do_not_draw_surfaces", 69 | help="List of surfaces not to be drawn", 70 | type=str, default="") 71 | parser.add_argument("--do_not_draw_raybundles", 72 | help="List of raybundles not to be drawn", 73 | type=str, default="") 74 | parsed = parser.parse_args() 75 | 76 | # TODO: add materials via command line 77 | 78 | show_spot = parsed.showspot 79 | file_to_read = parsed.file 80 | enpd = parsed.epd 81 | num_rays = parsed.numrays 82 | bundletype = parsed.bundletype 83 | anglex = parsed.anglex 84 | reverse = parsed.reverse 85 | surfaces_do_not_draw = parsed.do_not_draw_surfaces.split(",") 86 | raybundles_do_not_draw = [int(s) for s in parsed.do_not_draw_raybundles.split(",") if s != ''] 87 | 88 | p = ZMXParser(file_to_read, name='ZMXParser') 89 | lctmp = LocalCoordinates.p("tmp") 90 | 91 | matdict = {"BK7": ConstantIndexGlass.p(lctmp, 1.5168), 92 | "LAFN21": ConstantIndexGlass.p(lctmp, 1.788), 93 | "SF53": ConstantIndexGlass.p(lctmp, 1.72)} 94 | 95 | (s, seq) = p.create_optical_system(matdict) 96 | 97 | if s is None: 98 | sys.exit() 99 | 100 | initialbundles_dict = p.create_initial_bundle() 101 | 102 | osa = OpticalSystemAnalysis(s, seq, name="Analysis") 103 | 104 | ray_paths = [] 105 | 106 | if initialbundles_dict == []: 107 | initialbundles_dict = [{"radius": enpd*0.5}] 108 | 109 | for d in initialbundles_dict: 110 | if show_spot: 111 | d["raster"] = raster.RectGrid() 112 | osa.aim(num_rays*num_rays, d, wave=standard_wavelength) 113 | osa.draw_spotdiagram() 114 | else: 115 | d["raster"] = raster.MeridionalFan() 116 | d["anglex"] = anglex 117 | osa.aim(num_rays, d, wave=standard_wavelength) 118 | ray_paths.append(osa.trace()[0]) 119 | 120 | if not show_spot: 121 | draw(s, ray_paths, do_not_draw_surfaces=surfaces_do_not_draw, 122 | do_not_draw_raybundles=raybundles_do_not_draw) 123 | else: 124 | plt.show() 125 | osa.prettyprint() 126 | --------------------------------------------------------------------------------