From b778becb18383e961a2480b4d4376d29338ca711 Mon Sep 17 00:00:00 2001 From: Jan Caron <j.caron@fz-juelich.de> Date: Mon, 29 Feb 2016 00:58:20 +0100 Subject: [PATCH] Commit after Reformatting with PyCharms! --- .idea/Pyramid.iml | 5 +- .idea/inspectionProfiles/Project_Default.xml | 55 +- .idea/scopes/__c.xml | 3 + .idea/scopes/__init__.xml | 3 + .idea/workspace.xml | 825 +++++++++--------- docs/Makefile | 79 +- docs/conf.py | 817 +++++++++-------- docs/index.rst | 46 +- docs/make.bat | 460 +++++----- docs/pyramid.rst | 64 +- pyramid/__init__.py | 33 +- pyramid/analytic.py | 91 +- pyramid/colormap.py | 64 +- pyramid/config.py | 4 +- pyramid/costfunction.py | 33 +- pyramid/dataset.py | 85 +- pyramid/diagnostics.py | 89 +- pyramid/fft.py | 123 ++- pyramid/forwardmodel.py | 97 +- pyramid/kernel.py | 76 +- pyramid/magcreator.py | 101 +-- pyramid/magdata.py | 171 ++-- pyramid/phasemap.py | 159 ++-- pyramid/phasemapper.py | 319 ++++--- pyramid/projector.py | 336 +++---- pyramid/quaternion.py | 64 +- pyramid/ramp.py | 40 +- pyramid/reconstruction.py | 20 +- pyramid/regularisator.py | 87 +- pyramid/template.x3d | 152 ---- pyramid/tests/pep8_log.txt | 49 -- pyramid/tests/test_analytic.py | 34 +- pyramid/tests/test_costfunction.py | 8 +- pyramid/tests/test_dataset.py | 12 +- pyramid/tests/test_forwardmodel.py | 6 +- pyramid/tests/test_kernel.py | 2 - pyramid/tests/test_magcreator.py | 4 +- pyramid/tests/test_magdata.py | 8 +- pyramid/tests/test_phasemap.py | 4 +- pyramid/tests/test_phasemapper.py | 9 +- pyramid/tests/test_projector.py | 33 +- pyramid/tests/test_regularisator.py | 22 +- pyramid/version.py | 7 +- scripts/gui/mag_slicer.py | 6 +- .../reconstruction_3d_from_magdata.py | 8 +- setup.py | 77 +- 46 files changed, 2493 insertions(+), 2297 deletions(-) create mode 100644 .idea/scopes/__c.xml create mode 100644 .idea/scopes/__init__.xml delete mode 100644 pyramid/template.x3d delete mode 100644 pyramid/tests/pep8_log.txt diff --git a/.idea/Pyramid.iml b/.idea/Pyramid.iml index c6a70c6..5eca370 100644 --- a/.idea/Pyramid.iml +++ b/.idea/Pyramid.iml @@ -3,7 +3,6 @@ <component name="NewModuleRootManager"> <content url="file://$MODULE_DIR$"> <sourceFolder url="file://$MODULE_DIR$/pyramid" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/scripts" isTestSource="false" /> </content> <orderEntry type="jdk" jdkName="Python 2.7.11 (C:\Anaconda2\python.exe)" jdkType="Python SDK" /> <orderEntry type="sourceFolder" forTests="false" /> @@ -12,6 +11,10 @@ <orderEntry type="module" module-name="Publications" /> <orderEntry type="module" module-name="Script-Vault" /> </component> + <component name="ReSTService"> + <option name="workdir" value="$MODULE_DIR$" /> + <option name="DOC_DIR" value="$MODULE_DIR$" /> + </component> <component name="TestRunnerService"> <option name="projectConfiguration" value="Nosetests" /> <option name="PROJECT_TEST_RUNNER" value="Nosetests" /> diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 1f0a149..ab12237 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -1,12 +1,63 @@ <component name="InspectionProjectProfileManager"> <profile version="1.0"> <option name="myName" value="Project Default" /> - <inspection_tool class="LongLine" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="LongLine" enabled="true" level="WARNING" enabled_by_default="true"> + <scope name="*.c" level="WARNING" enabled="false" /> + </inspection_tool> + <inspection_tool class="PyAttributeOutsideInitInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" /> + <inspection_tool class="PyBroadExceptionInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" /> + <inspection_tool class="PyClassicStyleClassInspection" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="ourVersions"> + <value> + <list size="1"> + <item index="0" class="java.lang.String" itemvalue="3.5" /> + </list> + </value> + </option> + </inspection_tool> + <inspection_tool class="PyMandatoryEncodingInspection" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="PyMissingOrEmptyDocstringInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> + <inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="ignoredPackages"> + <value> + <list size="1"> + <item index="0" class="java.lang.String" itemvalue="hyperspy" /> + </list> + </value> + </option> + </inspection_tool> + <inspection_tool class="PyPep8Inspection" enabled="true" level="WEAK WARNING" enabled_by_default="true"> + <scope name="__init__" level="WEAK WARNING" enabled="true"> + <option name="ignoredErrors"> + <list> + <option value="E402" /> + </list> + </option> + </scope> + <option name="ignoredErrors"> + <list> + <option value="W503" /> + </list> + </option> + </inspection_tool> + <inspection_tool class="PyPep8NamingInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" /> + <inspection_tool class="PyShadowingNamesInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" /> + <inspection_tool class="PyTypeCheckerInspection" enabled="false" level="WARNING" enabled_by_default="false" /> + <inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true"> + <scope name="__init__" level="WARNING" enabled="false" /> + <option name="ignoredIdentifiers"> + <list> + <option value="multiprocessing" /> + <option value="hyperspy.api" /> + </list> + </option> + </inspection_tool> <inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false"> <option name="processCode" value="true" /> <option name="processLiterals" value="true" /> <option name="processComments" value="true" /> </inspection_tool> - <inspection_tool class="TodoComment" enabled="true" level="INFO" enabled_by_default="true" /> + <inspection_tool class="TodoComment" enabled="false" level="INFO" enabled_by_default="false" /> </profile> </component> \ No newline at end of file diff --git a/.idea/scopes/__c.xml b/.idea/scopes/__c.xml new file mode 100644 index 0000000..29b9103 --- /dev/null +++ b/.idea/scopes/__c.xml @@ -0,0 +1,3 @@ +<component name="DependencyValidationManager"> + <scope name="*.c" pattern="file[Pyramid]:pyramid/numcore/*.c" /> +</component> \ No newline at end of file diff --git a/.idea/scopes/__init__.xml b/.idea/scopes/__init__.xml new file mode 100644 index 0000000..067b2ec --- /dev/null +++ b/.idea/scopes/__init__.xml @@ -0,0 +1,3 @@ +<component name="DependencyValidationManager"> + <scope name="__init__" pattern="file[Pyramid]:pyramid/__init__.py" /> +</component> \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index bc561c2..b1a5b78 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,17 +1,57 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="AnalysisUIOptions"> - <option name="SCOPE_TYPE" value="4" /> + <option name="SCOPE_TYPE" value="3" /> <option name="ANALYSIS_IN_BACKGROUND" value="true" /> </component> <component name="ChangeListManager"> - <list default="true" id="990252ab-aff5-4ac2-a857-b193d2c46b18" name="Default" comment="Hopefully made hyperspy import (now at beginning of pyramid package) work! Added PyCharm files! Commit before Reformatting with PyCharms!"> - <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/../HyperSpy/hyperspy/_signals/holography_image.py" /> - <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/../HyperSpy/hyperspy/_signals/phase_image.py" /> - <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/../HyperSpy/hyperspy/_signals/utils.py" /> - <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/.idea/workspace.xml" /> - <change type="MODIFICATION" beforePath="$PROJECT_DIR$/../HyperSpy/.hgignore" afterPath="$PROJECT_DIR$/../HyperSpy/.hgignore" /> - <change type="MODIFICATION" beforePath="$PROJECT_DIR$/../HyperSpy/hyperspy/signals.py" afterPath="$PROJECT_DIR$/../HyperSpy/hyperspy/signals.py" /> + <list default="true" id="990252ab-aff5-4ac2-a857-b193d2c46b18" name="Default" comment="Commit after Reformatting with PyCharms!"> + <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/.idea/scopes/__c.xml" /> + <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/.idea/scopes/__init__.xml" /> + <change type="DELETED" beforePath="$PROJECT_DIR$/pyramid/template.x3d" afterPath="" /> + <change type="DELETED" beforePath="$PROJECT_DIR$/pyramid/tests/pep8_log.txt" afterPath="" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/Pyramid.iml" afterPath="$PROJECT_DIR$/.idea/Pyramid.iml" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/inspectionProfiles/Project_Default.xml" afterPath="$PROJECT_DIR$/.idea/inspectionProfiles/Project_Default.xml" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/docs/Makefile" afterPath="$PROJECT_DIR$/docs/Makefile" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/docs/conf.py" afterPath="$PROJECT_DIR$/docs/conf.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/docs/index.rst" afterPath="$PROJECT_DIR$/docs/index.rst" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/docs/make.bat" afterPath="$PROJECT_DIR$/docs/make.bat" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/docs/pyramid.rst" afterPath="$PROJECT_DIR$/docs/pyramid.rst" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/__init__.py" afterPath="$PROJECT_DIR$/pyramid/__init__.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/analytic.py" afterPath="$PROJECT_DIR$/pyramid/analytic.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/colormap.py" afterPath="$PROJECT_DIR$/pyramid/colormap.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/config.py" afterPath="$PROJECT_DIR$/pyramid/config.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/costfunction.py" afterPath="$PROJECT_DIR$/pyramid/costfunction.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/dataset.py" afterPath="$PROJECT_DIR$/pyramid/dataset.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/diagnostics.py" afterPath="$PROJECT_DIR$/pyramid/diagnostics.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/fft.py" afterPath="$PROJECT_DIR$/pyramid/fft.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/forwardmodel.py" afterPath="$PROJECT_DIR$/pyramid/forwardmodel.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/kernel.py" afterPath="$PROJECT_DIR$/pyramid/kernel.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/magcreator.py" afterPath="$PROJECT_DIR$/pyramid/magcreator.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/magdata.py" afterPath="$PROJECT_DIR$/pyramid/magdata.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/phasemap.py" afterPath="$PROJECT_DIR$/pyramid/phasemap.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/phasemapper.py" afterPath="$PROJECT_DIR$/pyramid/phasemapper.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/projector.py" afterPath="$PROJECT_DIR$/pyramid/projector.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/quaternion.py" afterPath="$PROJECT_DIR$/pyramid/quaternion.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/ramp.py" afterPath="$PROJECT_DIR$/pyramid/ramp.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/reconstruction.py" afterPath="$PROJECT_DIR$/pyramid/reconstruction.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/regularisator.py" afterPath="$PROJECT_DIR$/pyramid/regularisator.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/tests/test_analytic.py" afterPath="$PROJECT_DIR$/pyramid/tests/test_analytic.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/tests/test_costfunction.py" afterPath="$PROJECT_DIR$/pyramid/tests/test_costfunction.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/tests/test_dataset.py" afterPath="$PROJECT_DIR$/pyramid/tests/test_dataset.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/tests/test_forwardmodel.py" afterPath="$PROJECT_DIR$/pyramid/tests/test_forwardmodel.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/tests/test_kernel.py" afterPath="$PROJECT_DIR$/pyramid/tests/test_kernel.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/tests/test_magcreator.py" afterPath="$PROJECT_DIR$/pyramid/tests/test_magcreator.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/tests/test_magdata.py" afterPath="$PROJECT_DIR$/pyramid/tests/test_magdata.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/tests/test_phasemap.py" afterPath="$PROJECT_DIR$/pyramid/tests/test_phasemap.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/tests/test_phasemapper.py" afterPath="$PROJECT_DIR$/pyramid/tests/test_phasemapper.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/tests/test_projector.py" afterPath="$PROJECT_DIR$/pyramid/tests/test_projector.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/tests/test_regularisator.py" afterPath="$PROJECT_DIR$/pyramid/tests/test_regularisator.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyramid/version.py" afterPath="$PROJECT_DIR$/pyramid/version.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/scripts/gui/mag_slicer.py" afterPath="$PROJECT_DIR$/scripts/gui/mag_slicer.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/scripts/reconstruction/reconstruction_3d_from_magdata.py" afterPath="$PROJECT_DIR$/scripts/reconstruction/reconstruction_3d_from_magdata.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/setup.py" afterPath="$PROJECT_DIR$/setup.py" /> </list> <ignored path="Pyramid.iws" /> <ignored path=".idea/workspace.xml" /> @@ -26,165 +66,16 @@ <component name="CreatePatchCommitExecutor"> <option name="PATCH_PATH" value="" /> </component> + <component name="ErrorTreeViewConfiguration"> + <option name="autoscrollToSource" value="true" /> + <option name="IS_AUTOSCROLL_TO_SOURCE" value="true" /> + </component> <component name="ExecutionTargetManager" SELECTED_TARGET="default_target" /> <component name="FavoritesManager"> <favorites_list name="Pyramid" /> </component> <component name="FileEditorManager"> - <leaf SIDE_TABS_SIZE_LIMIT_KEY="300"> - <file leaf-file-name="dataset.py" pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/pyramid/dataset.py"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="8" column="0" selection-start-line="8" selection-start-column="0" selection-end-line="8" selection-end-column="0" /> - <folding /> - </state> - </provider> - </entry> - </file> - <file leaf-file-name="diagnostics.py" pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/pyramid/diagnostics.py"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="127" column="34" selection-start-line="127" selection-start-column="34" selection-end-line="127" selection-end-column="34" /> - <folding> - <element signature="e#261#279#0" expanded="false" /> - </folding> - </state> - </provider> - </entry> - </file> - <file leaf-file-name="magdata.py" pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/pyramid/magdata.py"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="221" column="21" selection-start-line="221" selection-start-column="21" selection-end-line="221" selection-end-column="21" /> - <folding /> - </state> - </provider> - </entry> - </file> - <file leaf-file-name="paper2_part3_experiment.py" pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/../Publications/paper 2/paper2_part3_experiment.py"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="12" column="0" selection-start-line="12" selection-start-column="0" selection-end-line="12" selection-end-column="0" /> - <folding /> - </state> - </provider> - </entry> - </file> - <file leaf-file-name="nanowire_z_angle.py" pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/../Publications/nanowire_z_angle.py"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="18" column="37" selection-start-line="18" selection-start-column="37" selection-end-line="18" selection-end-column="37" /> - <folding /> - </state> - </provider> - </entry> - </file> - <file leaf-file-name="poster_pico2015_2d.py" pinned="false" current-in-tab="true"> - <entry file="file://$PROJECT_DIR$/../Publications/pico 2015/poster_pico2015_2d.py"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.44790256"> - <caret line="36" column="62" selection-start-line="36" selection-start-column="62" selection-end-line="36" selection-end-column="62" /> - <folding /> - </state> - </provider> - </entry> - </file> - <file leaf-file-name="phasemap.py" pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/pyramid/phasemap.py"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="331" column="45" selection-start-line="331" selection-start-column="45" selection-end-line="331" selection-end-column="45" /> - <folding /> - </state> - </provider> - </entry> - </file> - <file leaf-file-name="phasemap_creator.py" pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/scripts/gui/phasemap_creator.py"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="260" column="58" selection-start-line="260" selection-start-column="58" selection-end-line="260" selection-end-column="58" /> - <folding /> - </state> - </provider> - </entry> - </file> - <file leaf-file-name="colormap.py" pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/pyramid/colormap.py"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="243" column="32" selection-start-line="243" selection-start-column="32" selection-end-line="243" selection-end-column="32" /> - <folding /> - </state> - </provider> - </entry> - </file> - <file leaf-file-name="pyramid.numcore.rst" pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/docs/pyramid.numcore.rst"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="9" column="0" selection-start-line="9" selection-start-column="0" selection-end-line="9" selection-end-column="0" /> - <folding /> - </state> - </provider> - </entry> - </file> - <file leaf-file-name="analytic.py" pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/pyramid/analytic.py"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="12" column="0" selection-start-line="12" selection-start-column="0" selection-end-line="12" selection-end-column="0" /> - <folding /> - </state> - </provider> - </entry> - </file> - <file leaf-file-name="__init__.py" pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/pyramid/__init__.py"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="57" column="0" selection-start-line="57" selection-start-column="0" selection-end-line="57" selection-end-column="0" /> - <folding /> - </state> - </provider> - </entry> - </file> - <file leaf-file-name="setup.py" pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/setup.py"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="13" column="0" selection-start-line="13" selection-start-column="0" selection-end-line="13" selection-end-column="0" /> - <folding /> - </state> - </provider> - </entry> - </file> - <file leaf-file-name="__init__.py" pinned="false" current-in-tab="false"> - <entry file="file://C:/Anaconda2/Lib/site-packages/pyface/qt/__init__.py"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="30" column="23" selection-start-line="30" selection-start-column="23" selection-end-line="30" selection-end-column="23" /> - <folding /> - </state> - </provider> - </entry> - </file> - <file leaf-file-name="test_phasemapper.py" pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/pyramid/tests/test_phasemapper.py"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="2" column="0" selection-start-line="2" selection-start-column="0" selection-end-line="2" selection-end-column="0" /> - <folding /> - </state> - </provider> - </entry> - </file> - </leaf> + <leaf SIDE_TABS_SIZE_LIMIT_KEY="300" /> </component> <component name="HgUpdateConfigurationSettings"> <option name="updateType" value="MERGE" /> @@ -194,20 +85,60 @@ <option name="CHANGED_PATHS"> <list> <option value="$APPLICATION_CONFIG_DIR$/consoles/ide/ide-scripting.groovy" /> - <option value="$PROJECT_DIR$/pyramid/diagnostics.py" /> <option value="$PROJECT_DIR$/../HyperSpy/.hgignore" /> <option value="$PROJECT_DIR$/scripts/magdata/magcreator/create_array_sphere_disc_slab.py" /> - <option value="$PROJECT_DIR$/pyramid/tests/test_phasemapper.py" /> - <option value="$PROJECT_DIR$/pyramid/__init__.py" /> - <option value="$PROJECT_DIR$/pyramid/magdata.py" /> - <option value="$PROJECT_DIR$/pyramid/phasemap.py" /> - <option value="$PROJECT_DIR$/pyramid/colormap.py" /> <option value="$PROJECT_DIR$/../Publications/paper 2/paper2_part3_experiment.py" /> <option value="$PROJECT_DIR$/../Publications/nanowire_z_angle.py" /> <option value="$PROJECT_DIR$/../Publications/pico 2015/poster_pico2015_2d.py" /> + <option value="$PROJECT_DIR$/pyramid/numcore/__init__.py" /> + <option value="$PROJECT_DIR$/../HyperSpy/hyperspy/_signals/phase_image.py" /> + <option value="$PROJECT_DIR$/../HyperSpy/hyperspy/signals.py" /> + <option value="$PROJECT_DIR$/scripts/gui/mag_slicer.py" /> + <option value="$PROJECT_DIR$/pyramid/costfunction.py" /> + <option value="$PROJECT_DIR$/pyramid/projector.py" /> + <option value="$PROJECT_DIR$/pyramid/reconstruction.py" /> + <option value="$PROJECT_DIR$/pyramid/regularisator.py" /> + <option value="$PROJECT_DIR$/pyramid/dataset.py" /> + <option value="$PROJECT_DIR$/pyramid/kernel.py" /> + <option value="$PROJECT_DIR$/docs/index.rst" /> + <option value="$PROJECT_DIR$/docs/pyramid.rst" /> + <option value="$PROJECT_DIR$/pyramid/colormap.py" /> + <option value="$PROJECT_DIR$/pyramid/ramp.py" /> + <option value="$PROJECT_DIR$/docs/conf.py" /> + <option value="$PROJECT_DIR$/pyramid/magcreator.py" /> + <option value="$PROJECT_DIR$/pyramid/phasemap.py" /> + <option value="$PROJECT_DIR$/pyramid/quaternion.py" /> + <option value="$PROJECT_DIR$/scripts/reconstruction/reconstruction_3d_from_magdata.py" /> + <option value="$PROJECT_DIR$/pyramid/forwardmodel.py" /> + <option value="$PROJECT_DIR$/pyramid/magdata.py" /> + <option value="$PROJECT_DIR$/pyramid/diagnostics.py" /> + <option value="$PROJECT_DIR$/pyramid/fft.py" /> + <option value="$PROJECT_DIR$/pyramid/phasemapper.py" /> + <option value="$PROJECT_DIR$/pyramid/version.py" /> + <option value="$PROJECT_DIR$/setup.py" /> + <option value="$PROJECT_DIR$/pyramid/tests/test_dataset.py" /> + <option value="$PROJECT_DIR$/pyramid/tests/test_phasemap.py" /> + <option value="$PROJECT_DIR$/pyramid/tests/test_magdata.py" /> + <option value="$PROJECT_DIR$/pyramid/tests/test_magcreator.py" /> + <option value="$PROJECT_DIR$/pyramid/tests/test_kernel.py" /> + <option value="$PROJECT_DIR$/pyramid/tests/test_forwardmodel.py" /> + <option value="$PROJECT_DIR$/pyramid/tests/test_costfunction.py" /> + <option value="$PROJECT_DIR$/pyramid/tests/test_phasemapper.py" /> + <option value="$PROJECT_DIR$/pyramid/tests/test_projector.py" /> + <option value="$PROJECT_DIR$/pyramid/tests/test_regularisator.py" /> + <option value="$PROJECT_DIR$/pyramid/tests/test_analytic.py" /> + <option value="$PROJECT_DIR$/pyramid/config.py" /> + <option value="$PROJECT_DIR$/pyramid/analytic.py" /> + <option value="$PROJECT_DIR$/pyramid/__init__.py" /> </list> </option> </component> + <component name="NamedScopeManager"> + <order> + <scope name="__init__" /> + <scope name="*.c" /> + </order> + </component> <component name="ProjectFrameBounds"> <option name="x" value="-8" /> <option name="y" value="-8" /> @@ -233,7 +164,7 @@ </expanded-state> <selected-state> <State> - <id>TodoComment</id> + <id>LongLine</id> </State> </selected-state> </profile-state> @@ -279,7 +210,7 @@ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" /> </PATH_ELEMENT> <PATH_ELEMENT> - <option name="myItemId" value="Script-Vault" /> + <option name="myItemId" value="Pyramid" /> <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" /> </PATH_ELEMENT> </PATH> @@ -292,6 +223,14 @@ <option name="myItemId" value="Pyramid" /> <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" /> </PATH_ELEMENT> + <PATH_ELEMENT> + <option name="myItemId" value="scripts" /> + <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" /> + </PATH_ELEMENT> + <PATH_ELEMENT> + <option name="myItemId" value="reconstruction" /> + <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" /> + </PATH_ELEMENT> </PATH> <PATH> <PATH_ELEMENT> @@ -303,7 +242,7 @@ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" /> </PATH_ELEMENT> <PATH_ELEMENT> - <option name="myItemId" value="pyramid" /> + <option name="myItemId" value="scripts" /> <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" /> </PATH_ELEMENT> </PATH> @@ -320,10 +259,6 @@ <option name="myItemId" value="pyramid" /> <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" /> </PATH_ELEMENT> - <PATH_ELEMENT> - <option name="myItemId" value="tests" /> - <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" /> - </PATH_ELEMENT> </PATH> </subPane> </pane> @@ -355,12 +290,32 @@ </PATH> </subPane> </pane> + <pane id="ColorIdeProjectViewPane"> + <subPane> + <PATH> + <PATH_ELEMENT> + <option name="myItemId" value="Pyramid" /> + <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" /> + </PATH_ELEMENT> + </PATH> + <PATH> + <PATH_ELEMENT> + <option name="myItemId" value="Pyramid" /> + <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" /> + </PATH_ELEMENT> + <PATH_ELEMENT> + <option name="myItemId" value="Pyramid" /> + <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" /> + </PATH_ELEMENT> + </PATH> + </subPane> + </pane> </panes> </component> <component name="PropertiesComponent"> - <property name="settings.editor.selected.configurable" value="project.propVCSSupport.Confirmation" /> + <property name="settings.editor.selected.configurable" value="preferences.sourceCode.Python" /> <property name="settings.editor.splitter.proportion" value="0.2" /> - <property name="last_opened_file_path" value="$PROJECT_DIR$/../Jutil" /> + <property name="last_opened_file_path" value="$PROJECT_DIR$/docs/_build" /> <property name="FileHistory.org.zmlx.hg4idea.provider.HgHistoryProvider_flatWidth0" value="44" /> <property name="FileHistory.org.zmlx.hg4idea.provider.HgHistoryProvider_flatOrder0" value="0" /> <property name="FileHistory.org.zmlx.hg4idea.provider.HgHistoryProvider_flatWidth1" value="64" /> @@ -377,11 +332,12 @@ <property name="FileHistory.org.zmlx.hg4idea.provider.HgHistoryProvider_treeOrder2" value="2" /> <property name="FileHistory.org.zmlx.hg4idea.provider.HgHistoryProvider_treeWidth3" value="306" /> <property name="FileHistory.org.zmlx.hg4idea.provider.HgHistoryProvider_treeOrder3" value="3" /> + <property name="last.edited.regexp" value="asdf aasfasf.version_info " /> </component> <component name="PyConsoleOptionsProvider"> <option name="myPythonConsoleState"> - <console-settings custom-start-script="from __future__ import division import sys import os import pdb import pyramid from pyramid import * import pyramid.analytic as an import pyramid.magcreator as mc import pyramid.reconstruction as rc import jutil import numpy as np import scipy as sp import matplotlib as mpl import matplotlib.pyplot as plt from pylab import * ion() # Enable Matplotlib's interactive mode sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS])" module-name="Pyramid" is-module-sdk="true" working-directory="$PROJECT_DIR$/files/magdata"> - <option name="myCustomStartScript" value="from __future__ import division import sys import os import pdb import pyramid from pyramid import * import pyramid.analytic as an import pyramid.magcreator as mc import pyramid.reconstruction as rc import jutil import numpy as np import scipy as sp import matplotlib as mpl import matplotlib.pyplot as plt from pylab import * ion() # Enable Matplotlib's interactive mode sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS])" /> + <console-settings custom-start-script="from __future__ import division import sys import os import pdb import hyperspy.api as hs import pyramid from pyramid import * import pyramid.analytic as an import pyramid.magcreator as mc import pyramid.reconstruction as rc import jutil import numpy as np import scipy as sp import matplotlib as mpl import matplotlib.pyplot as plt from pylab import * ion() # Enable Matplotlib's interactive mode sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS])" module-name="Pyramid" is-module-sdk="true" working-directory="$PROJECT_DIR$/files/magdata"> + <option name="myCustomStartScript" value="from __future__ import division import sys import os import pdb import hyperspy.api as hs import pyramid from pyramid import * import pyramid.analytic as an import pyramid.magcreator as mc import pyramid.reconstruction as rc import jutil import numpy as np import scipy as sp import matplotlib as mpl import matplotlib.pyplot as plt from pylab import * ion() # Enable Matplotlib's interactive mode sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS])" /> <option name="myUseModuleSdk" value="true" /> <option name="myModuleName" value="Pyramid" /> <option name="myWorkingDirectory" value="$PROJECT_DIR$/files/magdata" /> @@ -389,6 +345,9 @@ </console-settings> </option> </component> + <component name="PyDebuggerOptionsProvider"> + <option name="mySaveCallSignatures" value="true" /> + </component> <component name="RecentsManager"> <key name="MoveFile.RECENT_KEYS"> <recent name="C:\Users\Jan\Home\PhD Thesis\Projects\Script-Vault" /> @@ -412,59 +371,72 @@ <option name="SHOW_COMMAND_LINE" value="true" /> <method /> </configuration> - <configuration default="false" name="create_array_sphere_disc_slab" type="PythonConfigurationType" factoryName="Python" temporary="true"> + <configuration default="false" name="phasemap" type="PythonConfigurationType" factoryName="Python" temporary="true"> <option name="INTERPRETER_OPTIONS" value="" /> <option name="PARENT_ENVS" value="true" /> <envs> <env name="PYTHONUNBUFFERED" value="1" /> </envs> - <option name="SDK_HOME" value="" /> - <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/scripts/magdata/magcreator" /> + <option name="SDK_HOME" value="C:\Anaconda2\python.exe" /> + <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/pyramid" /> <option name="IS_MODULE_SDK" value="true" /> <option name="ADD_CONTENT_ROOTS" value="true" /> <option name="ADD_SOURCE_ROOTS" value="true" /> <module name="Pyramid" /> - <option name="SCRIPT_NAME" value="$PROJECT_DIR$/scripts/magdata/magcreator/create_array_sphere_disc_slab.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/pyramid/phasemap.py" /> <option name="PARAMETERS" value="" /> <option name="SHOW_COMMAND_LINE" value="true" /> <method /> </configuration> - <configuration default="false" name="__init__" type="PythonConfigurationType" factoryName="Python" temporary="true"> + <configuration default="false" name="reconstruction_3d_from_magdata" type="PythonConfigurationType" factoryName="Python" temporary="true"> <option name="INTERPRETER_OPTIONS" value="" /> <option name="PARENT_ENVS" value="true" /> <envs> <env name="PYTHONUNBUFFERED" value="1" /> </envs> <option name="SDK_HOME" value="C:\Anaconda2\python.exe" /> - <option name="WORKING_DIRECTORY" value="C:/Anaconda2/Lib/site-packages/pyface/qt" /> + <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/scripts/reconstruction" /> <option name="IS_MODULE_SDK" value="true" /> <option name="ADD_CONTENT_ROOTS" value="true" /> <option name="ADD_SOURCE_ROOTS" value="true" /> <module name="Script-Vault" /> - <option name="SCRIPT_NAME" value="C:/Anaconda2/Lib/site-packages/pyface/qt/__init__.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/scripts/reconstruction/reconstruction_3d_from_magdata.py" /> <option name="PARAMETERS" value="" /> <option name="SHOW_COMMAND_LINE" value="true" /> <method /> </configuration> - <configuration default="false" name="Nosetest TestCasePhaseMapperRDFC.test_PhaseMapperRDFC_call" type="tests" factoryName="Nosetests" temporary="true" nameIsGenerated="true"> + <configuration default="false" name="fft" type="PythonConfigurationType" factoryName="Python" temporary="true"> <option name="INTERPRETER_OPTIONS" value="" /> <option name="PARENT_ENVS" value="true" /> - <envs /> + <envs> + <env name="PYTHONUNBUFFERED" value="1" /> + </envs> <option name="SDK_HOME" value="C:\Anaconda2\python.exe" /> - <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/pyramid/tests" /> + <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/pyramid" /> <option name="IS_MODULE_SDK" value="true" /> <option name="ADD_CONTENT_ROOTS" value="true" /> <option name="ADD_SOURCE_ROOTS" value="true" /> <module name="Pyramid" /> - <option name="SCRIPT_NAME" value="$PROJECT_DIR$/pyramid/tests/test_phasemapper.py" /> - <option name="CLASS_NAME" value="TestCasePhaseMapperRDFC" /> - <option name="METHOD_NAME" value="test_PhaseMapperRDFC_call" /> - <option name="FOLDER_NAME" value="$PROJECT_DIR$/pyramid/tests" /> - <option name="TEST_TYPE" value="TEST_METHOD" /> - <option name="PATTERN" value="" /> - <option name="USE_PATTERN" value="false" /> - <option name="PARAMS" value="" /> - <option name="USE_PARAM" value="false" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/pyramid/fft.py" /> + <option name="PARAMETERS" value="" /> + <option name="SHOW_COMMAND_LINE" value="true" /> + <method /> + </configuration> + <configuration default="false" name="setup" type="PythonConfigurationType" factoryName="Python" temporary="true"> + <option name="INTERPRETER_OPTIONS" value="" /> + <option name="PARENT_ENVS" value="true" /> + <envs> + <env name="PYTHONUNBUFFERED" value="1" /> + </envs> + <option name="SDK_HOME" value="C:\Anaconda2\python.exe" /> + <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" /> + <option name="IS_MODULE_SDK" value="true" /> + <option name="ADD_CONTENT_ROOTS" value="true" /> + <option name="ADD_SOURCE_ROOTS" value="true" /> + <module name="Script-Vault" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/setup.py" /> + <option name="PARAMETERS" value="" /> + <option name="SHOW_COMMAND_LINE" value="true" /> <method /> </configuration> <configuration default="true" type="CompoundRunConfigurationType" factoryName="Compound Run Configuration"> @@ -620,7 +592,7 @@ <option name="ADD_SOURCE_ROOTS" value="true" /> <module name="Pyramid" /> <option name="docutils_input_file" value="C:\Users\Jan\Home\PhD Thesis\Projects\Pyramid\docs" /> - <option name="docutils_output_file" value="C:\Users\Jan\Home\PhD Thesis\Projects\Pyramid\Documentation" /> + <option name="docutils_output_file" value="C:\Users\Jan\Home\PhD Thesis\Projects\Pyramid\docs\_build" /> <option name="docutils_params" value="" /> <option name="docutils_task" value="html" /> <option name="docutils_open_in_browser" value="false" /> @@ -647,25 +619,28 @@ <option name="USE_PARAM" value="false" /> <method /> </configuration> - <list size="6"> + <list size="7"> <item index="0" class="java.lang.String" itemvalue="Python docs.Pyramid Sphinx" /> <item index="1" class="java.lang.String" itemvalue="Python tests.Pyramid Tests" /> <item index="2" class="java.lang.String" itemvalue="Python.mag_slicer" /> - <item index="3" class="java.lang.String" itemvalue="Python.create_array_sphere_disc_slab" /> - <item index="4" class="java.lang.String" itemvalue="Python.__init__" /> - <item index="5" class="java.lang.String" itemvalue="Python tests.Nosetest TestCasePhaseMapperRDFC.test_PhaseMapperRDFC_call" /> + <item index="3" class="java.lang.String" itemvalue="Python.phasemap" /> + <item index="4" class="java.lang.String" itemvalue="Python.reconstruction_3d_from_magdata" /> + <item index="5" class="java.lang.String" itemvalue="Python.fft" /> + <item index="6" class="java.lang.String" itemvalue="Python.setup" /> </list> <recent_temporary> - <list size="4"> - <item index="0" class="java.lang.String" itemvalue="Python.__init__" /> - <item index="1" class="java.lang.String" itemvalue="Python tests.Nosetest TestCasePhaseMapperRDFC.test_PhaseMapperRDFC_call" /> - <item index="2" class="java.lang.String" itemvalue="Python.create_array_sphere_disc_slab" /> - <item index="3" class="java.lang.String" itemvalue="Python.mag_slicer" /> + <list size="5"> + <item index="0" class="java.lang.String" itemvalue="Python.setup" /> + <item index="1" class="java.lang.String" itemvalue="Python.fft" /> + <item index="2" class="java.lang.String" itemvalue="Python.reconstruction_3d_from_magdata" /> + <item index="3" class="java.lang.String" itemvalue="Python.phasemap" /> + <item index="4" class="java.lang.String" itemvalue="Python.mag_slicer" /> </list> </recent_temporary> </component> <component name="ShelveChangesManager" show_recycled="false" /> <component name="StructureViewFactory"> + <option name="AUTOSCROLL_FROM_SOURCE" value="true" /> <option name="ACTIVE_ACTIONS" value=",SHOW_INHERITED,SHOW_FIELDS" /> </component> <component name="SvnConfiguration"> @@ -708,42 +683,54 @@ <option name="project" value="LOCAL" /> <updated>1456182073457</updated> </task> - <option name="localTasksCounter" value="6" /> + <task id="LOCAL-00006" summary="Hopefully made hyperspy import (now at beginning of pyramid package) work! Added PyCharm files! Commit before Reformatting with PyCharms!"> + <created>1456182098486</created> + <option name="number" value="00006" /> + <option name="project" value="LOCAL" /> + <updated>1456182098486</updated> + </task> + <task id="LOCAL-00007" summary="New branch: new signals for holographic analysis!"> + <created>1456209518394</created> + <option name="number" value="00007" /> + <option name="project" value="LOCAL" /> + <updated>1456209518394</updated> + </task> + <option name="localTasksCounter" value="8" /> <servers /> </component> <component name="TestHistory"> - <history-entry file="Nosetest_TestCasePhaseMapperRDFC_test_PhaseMapperRDFC_call - 2016.02.22 at 15h 25m 03s.xml"> - <configuration name="Nosetest TestCasePhaseMapperRDFC.test_PhaseMapperRDFC_call" configurationId="tests" /> + <history-entry file="Pyramid_Tests - 2016.02.25 at 12h 10m 06s.xml"> + <configuration name="Pyramid Tests" configurationId="tests" /> </history-entry> - <history-entry file="Nosetest_TestCasePhaseMapperRDFC_test_PhaseMapperRDFC_call - 2016.02.22 at 15h 25m 25s.xml"> - <configuration name="Nosetest TestCasePhaseMapperRDFC.test_PhaseMapperRDFC_call" configurationId="tests" /> + <history-entry file="Pyramid_Tests - 2016.02.25 at 12h 11m 44s.xml"> + <configuration name="Pyramid Tests" configurationId="tests" /> </history-entry> - <history-entry file="Nosetest_TestCasePhaseMapperRDFC_test_PhaseMapperRDFC_call - 2016.02.22 at 15h 51m 53s.xml"> - <configuration name="Nosetest TestCasePhaseMapperRDFC.test_PhaseMapperRDFC_call" configurationId="tests" /> + <history-entry file="Pyramid_Tests - 2016.02.25 at 12h 11m 50s.xml"> + <configuration name="Pyramid Tests" configurationId="tests" /> </history-entry> - <history-entry file="Pyramid_Tests - 2016.02.22 at 15h 52m 05s.xml"> + <history-entry file="Pyramid_Tests - 2016.02.26 at 16h 08m 01s.xml"> <configuration name="Pyramid Tests" configurationId="tests" /> </history-entry> - <history-entry file="Pyramid_Tests - 2016.02.22 at 16h 59m 07s.xml"> + <history-entry file="Pyramid_Tests - 2016.02.28 at 23h 04m 43s.xml"> <configuration name="Pyramid Tests" configurationId="tests" /> </history-entry> - <history-entry file="Pyramid_Tests - 2016.02.22 at 16h 59m 43s.xml"> + <history-entry file="Pyramid_Tests - 2016.02.28 at 23h 09m 16s.xml"> <configuration name="Pyramid Tests" configurationId="tests" /> </history-entry> - <history-entry file="Pyramid_Tests - 2016.02.22 at 17h 07m 21s.xml"> + <history-entry file="Pyramid_Tests - 2016.02.28 at 23h 13m 11s.xml"> <configuration name="Pyramid Tests" configurationId="tests" /> </history-entry> - <history-entry file="Pyramid_Tests - 2016.02.22 at 17h 08m 46s.xml"> + <history-entry file="Pyramid_Tests - 2016.02.28 at 23h 56m 53s.xml"> <configuration name="Pyramid Tests" configurationId="tests" /> </history-entry> - <history-entry file="Pyramid_Tests - 2016.02.22 at 17h 16m 21s.xml"> + <history-entry file="Pyramid_Tests - 2016.02.29 at 00h 18m 56s.xml"> <configuration name="Pyramid Tests" configurationId="tests" /> </history-entry> - <history-entry file="Pyramid_Tests - 2016.02.22 at 17h 37m 39s.xml"> + <history-entry file="Pyramid_Tests - 2016.02.29 at 00h 21m 13s.xml"> <configuration name="Pyramid Tests" configurationId="tests" /> </history-entry> </component> - <component name="TodoView"> + <component name="TodoView" selected-index="3"> <todo-panel id="selected-file"> <is-autoscroll-to-source value="true" /> </todo-panel> @@ -754,27 +741,27 @@ </component> <component name="ToolWindowManager"> <frame x="-8" y="-8" width="1616" height="876" extended-state="6" /> - <editor active="true" /> + <editor active="false" /> <layout> - <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.17609255" sideWeight="0.49186993" order="0" side_tool="false" content_ui="combo" /> <window_info id="TODO" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.40616965" sideWeight="0.49746513" order="9" side_tool="false" content_ui="tabs" x="-33" y="355" width="1594" height="283" /> - <window_info id="Messages" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3566838" sideWeight="0.5" order="12" side_tool="false" content_ui="tabs" /> - <window_info id="Event Log" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4293059" sideWeight="0.50253487" order="8" side_tool="false" content_ui="tabs" /> - <window_info id="Python Console" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33097687" sideWeight="0.49746513" order="3" side_tool="false" content_ui="tabs" /> + <window_info id="Messages" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33290488" sideWeight="0.5" order="12" side_tool="false" content_ui="tabs" /> + <window_info id="Event Log" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.42866325" sideWeight="0.50253487" order="8" side_tool="false" content_ui="tabs" /> + <window_info id="Inspection" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.37596402" sideWeight="0.5" order="10" side_tool="false" content_ui="tabs" /> + <window_info id="Python Console" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.51349616" sideWeight="0.49746513" order="3" side_tool="false" content_ui="tabs" /> <window_info id="Version Control" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4415167" sideWeight="0.49746513" order="7" side_tool="false" content_ui="tabs" /> - <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.15085287" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" /> - <window_info id="Terminal" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4336" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" /> + <window_info id="Run" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.41773778" sideWeight="0.49746513" order="4" side_tool="false" content_ui="tabs" /> + <window_info id="Terminal" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.43316194" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" /> + <window_info id="Project" active="true" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.18508998" sideWeight="0.49186993" order="0" side_tool="false" content_ui="combo" /> + <window_info id="Find" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.41791046" sideWeight="0.5" order="13" side_tool="false" content_ui="tabs" /> + <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.087403595" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" /> <window_info id="Favorites" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.4224" sideWeight="0.5081301" order="11" side_tool="false" content_ui="tabs" /> + <window_info id="Debug" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.40565032" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" /> <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" /> <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" /> <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" /> - <window_info id="Inspection" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.48650387" sideWeight="0.5" order="10" side_tool="false" content_ui="tabs" /> - <window_info id="Run" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4248072" sideWeight="0.49746513" order="4" side_tool="false" content_ui="tabs" /> <window_info id="Thumbnails" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="WINDOWED" visible="false" show_stripe_button="false" weight="0.3708108" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" x="6" y="307" width="1908" height="381" /> <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" /> - <window_info id="Find" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.41897655" sideWeight="0.5" order="13" side_tool="false" content_ui="tabs" /> <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" /> - <window_info id="Debug" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.43573266" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" /> </layout> </component> <component name="Vcs.Log.UiProperties"> @@ -790,6 +777,7 @@ <option name="myLimit" value="2678400000" /> </component> <component name="VcsManagerConfiguration"> + <option name="OFFER_MOVE_TO_ANOTHER_CHANGELIST_ON_PARTIAL_COMMIT" value="false" /> <option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="true" /> <option name="CHECK_CODE_CLEANUP_BEFORE_PROJECT_COMMIT" value="true" /> <confirmMoveToFailedCommit value="1" /> @@ -800,8 +788,9 @@ <MESSAGE value="First Publications commit! " /> <MESSAGE value="Added old backup copies (sort out in future)! " /> <MESSAGE value="Hopefully made hyperspy import (now at beginning of pyramid package) work! Added PyCharm files! Commit before Reformatting with PyCharms!" /> - <option name="LAST_COMMIT_MESSAGE" value="Hopefully made hyperspy import (now at beginning of pyramid package) work! Added PyCharm files! Commit before Reformatting with PyCharms!" /> - <option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="true" /> + <MESSAGE value="New branch: new signals for holographic analysis!" /> + <MESSAGE value="Commit after Reformatting with PyCharms!" /> + <option name="LAST_COMMIT_MESSAGE" value="Commit after Reformatting with PyCharms!" /> <option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="true" /> <option name="REARRANGE_BEFORE_PROJECT_COMMIT" value="true" /> <option name="CHANGE_BROWSER_SETTINGS"> @@ -819,406 +808,411 @@ </component> <component name="XDebuggerManager"> <breakpoint-manager> - <option name="time" value="9" /> + <breakpoints> + <line-breakpoint enabled="true" type="python-line"> + <url>file://$PROJECT_DIR$/../HyperSpy/hyperspy/io.py</url> + <line>343</line> + <option name="timeStamp" value="11" /> + </line-breakpoint> + </breakpoints> + <breakpoints-dialog> + <breakpoints-dialog /> + </breakpoints-dialog> + <option name="time" value="23" /> </breakpoint-manager> - <watches-manager /> + <watches-manager> + <configuration name="PythonConfigurationType"> + <watch expression="result.shape" /> + <watch expression="recv.shape" /> + <watch expression="sub_vec.shape" /> + </configuration> + </watches-manager> </component> <component name="editorHistoryManager"> - <entry file="file://$PROJECT_DIR$/pyramid/__init__.py"> + <entry file="file://$PROJECT_DIR$/../HyperSpy/hyperspy/io.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="10" column="7" selection-start-line="10" selection-start-column="7" selection-end-line="10" selection-end-column="7" /> + <state vertical-scroll-proportion="0.28687415"> + <caret line="342" column="54" selection-start-line="342" selection-start-column="54" selection-end-line="342" selection-end-column="54" /> <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/.hgignore"> + <entry file="file://C:/Anaconda2/Lib/site-packages/numpy/__init__.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> - <folding /> + <state vertical-scroll-proportion="0.20457019"> + <caret line="191" column="23" selection-start-line="191" selection-start-column="23" selection-end-line="191" selection-end-column="23" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/setup.py"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="13" column="44" selection-start-line="13" selection-start-column="44" selection-end-line="13" selection-end-column="44" /> - <folding /> - </state> - </provider> - </entry> - <entry file="file://$PROJECT_DIR$/pyramid/dataset.py"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> - <folding /> + <entry file="file://$PROJECT_DIR$/../../Notebooks/Current Line/Current line.ipynb"> + <provider selected="true" editor-type-id="ipnb-editor"> + <state> + <selected id="5" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyramid/diagnostics.py"> + <entry file="file://C:/Anaconda2/Lib/site-packages/pyface/qt/__init__.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="127" column="34" selection-start-line="127" selection-start-column="34" selection-end-line="127" selection-end-column="34" /> - <folding> - <element signature="e#261#279#0" expanded="false" /> - </folding> + <state vertical-scroll-proportion="0.36806494"> + <caret line="16" column="0" selection-start-line="16" selection-start-column="0" selection-end-line="16" selection-end-column="0" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyramid/magdata.py"> + <entry file="file://$PROJECT_DIR$/pyramid/regularisator.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> - <folding /> + <state vertical-scroll-proportion="5.8132186"> + <caret line="238" column="0" selection-start-line="238" selection-start-column="0" selection-end-line="238" selection-end-column="0" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/setup.py"> + <entry file="file://$PROJECT_DIR$/pyramid/reconstruction.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="13" column="44" selection-start-line="13" selection-start-column="44" selection-end-line="13" selection-end-column="44" /> - <folding /> + <state vertical-scroll-proportion="0.64511496"> + <caret line="28" column="0" selection-start-line="28" selection-start-column="0" selection-end-line="28" selection-end-column="0" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyramid/dataset.py"> + <entry file="file://$PROJECT_DIR$/pyramid/costfunction.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> - <folding /> + <state vertical-scroll-proportion="0.24425288"> + <caret line="10" column="0" selection-start-line="10" selection-start-column="0" selection-end-line="10" selection-end-column="0" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyramid/diagnostics.py"> + <entry file="file://$PROJECT_DIR$/pyramid/projector.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="127" column="34" selection-start-line="127" selection-start-column="34" selection-end-line="127" selection-end-column="34" /> - <folding> - <element signature="e#261#279#0" expanded="false" /> - </folding> + <state vertical-scroll-proportion="16.09064"> + <caret line="637" column="34" selection-start-line="637" selection-start-column="34" selection-end-line="637" selection-end-column="34" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyramid/magdata.py"> + <entry file="file://$PROJECT_DIR$/docs/Makefile"> <provider selected="true" editor-type-id="text-editor"> <state vertical-scroll-proportion="0.0"> <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> - <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/setup.py"> + <entry file="file://$PROJECT_DIR$/docs/make.bat"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="13" column="44" selection-start-line="13" selection-start-column="44" selection-end-line="13" selection-end-column="44" /> - <folding /> + <state vertical-scroll-proportion="-1.9860919"> + <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyramid/dataset.py"> + <entry file="file://$PROJECT_DIR$/docs/_static/sphinxdoc.css"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> + <state vertical-scroll-proportion="-0.9221141"> <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> - <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyramid/diagnostics.py"> + <entry file="file://$PROJECT_DIR$/docs/pyramid.numcore.rst"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="127" column="34" selection-start-line="127" selection-start-column="34" selection-end-line="127" selection-end-column="34" /> - <folding> - <element signature="e#261#279#0" expanded="false" /> - </folding> + <state vertical-scroll-proportion="0.21279556"> + <caret line="9" column="0" selection-start-line="9" selection-start-column="0" selection-end-line="9" selection-end-column="0" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyramid/magdata.py"> + <entry file="file://$PROJECT_DIR$/pyramid/ramp.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> - <folding /> + <state vertical-scroll-proportion="0.29310346"> + <caret line="47" column="26" selection-start-line="47" selection-start-column="26" selection-end-line="47" selection-end-column="26" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/setup.py"> + <entry file="file://$PROJECT_DIR$/docs/pyramid.rst"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="13" column="44" selection-start-line="13" selection-start-column="44" selection-end-line="13" selection-end-column="44" /> - <folding /> + <state vertical-scroll-proportion="0.6091954"> + <caret line="136" column="22" selection-start-line="136" selection-start-column="22" selection-end-line="136" selection-end-column="22" /> </state> </provider> </entry> - <entry file="file://$APPLICATION_CONFIG_DIR$/consoles/ide/ide-scripting.groovy"> + <entry file="file://$PROJECT_DIR$/docs/index.rst"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.040767387"> - <caret line="1" column="0" selection-start-line="1" selection-start-column="0" selection-end-line="1" selection-end-column="0" /> + <state vertical-scroll-proportion="0.31752872"> + <caret line="13" column="10" selection-start-line="13" selection-start-column="10" selection-end-line="13" selection-end-column="10" /> </state> </provider> </entry> - <entry file="file://$USER_HOME$/.PyCharm50/system/python_stubs/884504192/__builtin__.py"> + <entry file="file://$PROJECT_DIR$/docs/conf.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.33333334"> - <caret line="699" column="8" selection-start-line="699" selection-start-column="8" selection-end-line="699" selection-end-column="8" /> + <state vertical-scroll-proportion="0.38793105"> + <caret line="33" column="20" selection-start-line="33" selection-start-column="16" selection-end-line="33" selection-end-column="20" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/.idea/dictionaries/Jan.xml"> - <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> - </state> + <entry file="file://$PROJECT_DIR$/docs/icon.ico"> + <provider selected="true" editor-type-id="images"> + <state /> </provider> </entry> - <entry file="file://$PROJECT_DIR$/.hgignore"> + <entry file="file://$PROJECT_DIR$/pyramid/magcreator.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="8" column="4" selection-start-line="8" selection-start-column="4" selection-end-line="8" selection-end-column="4" /> + <state vertical-scroll-proportion="0.2836485"> + <caret line="99" column="94" selection-start-line="99" selection-start-column="94" selection-end-line="99" selection-end-column="94" /> <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/../Publications/.hgignore"> + <entry file="file://$PROJECT_DIR$/pyramid/colormap.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> + <state vertical-scroll-proportion="0.42407808"> + <caret line="23" column="9" selection-start-line="23" selection-start-column="9" selection-end-line="23" selection-end-column="9" /> <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/../Jutil/.hgignore"> + <entry file="file://$PROJECT_DIR$/pyramid/quaternion.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> + <state vertical-scroll-proportion="0.5021692"> + <caret line="119" column="24" selection-start-line="119" selection-start-column="24" selection-end-line="119" selection-end-column="24" /> + <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/../HyperSpy/.hgignore"> + <entry file="file://$PROJECT_DIR$/pyramid/logging.ini"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.4624592"> - <caret line="25" column="30" selection-start-line="25" selection-start-column="30" selection-end-line="25" selection-end-column="30" /> + <state vertical-scroll-proportion="0.59002167"> + <caret line="32" column="13" selection-start-line="32" selection-start-column="13" selection-end-line="32" selection-end-column="13" /> <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/../HyperSpy/.gitignore"> + <entry file="file://$PROJECT_DIR$/pyramid/forwardmodel.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> + <state vertical-scroll-proportion="0.5272525"> + <caret line="303" column="47" selection-start-line="303" selection-start-column="47" selection-end-line="303" selection-end-column="47" /> + <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/../HyperSpy/hyperspy/signals.py"> + <entry file="file://$PROJECT_DIR$/docs/_build/_static/underscore-1.3.1.js"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.8335147"> - <caret line="48" column="27" selection-start-line="48" selection-start-column="27" selection-end-line="48" selection-end-column="27" /> + <state vertical-scroll-proportion="0.3329718"> + <caret line="94" column="55" selection-start-line="94" selection-start-column="55" selection-end-line="94" selection-end-column="55" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/../HyperSpy/hyperspy/_signals/utils.py"> + <entry file="file://$PROJECT_DIR$/scripts/reconstruction/reconstruction_2d_from_phasemap.py"> <provider selected="true" editor-type-id="text-editor"> <state vertical-scroll-proportion="0.0"> <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/../HyperSpy/hyperspy/_signals/__init__.py"> + <entry file="file://$PROJECT_DIR$/pyramid/phasemap.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> + <state vertical-scroll-proportion="0.324295"> + <caret line="108" column="40" selection-start-line="108" selection-start-column="40" selection-end-line="108" selection-end-column="40" /> + <folding /> </state> </provider> </entry> - <entry file="file://$APPLICATION_HOME_DIR$/helpers/pydev/pydev_import_hook.py"> + <entry file="file://$PROJECT_DIR$/pyramid/magdata.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.36996734"> - <caret line="20" column="59" selection-start-line="20" selection-start-column="59" selection-end-line="20" selection-end-column="59" /> + <state vertical-scroll-proportion="0.44685465"> + <caret line="834" column="54" selection-start-line="834" selection-start-column="54" selection-end-line="834" selection-end-column="54" /> + <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/scripts/gui/mag_slicer.py"> + <entry file="file://$PROJECT_DIR$/../Jutil/jutil/cg.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.4573991"> - <caret line="24" column="4" selection-start-line="24" selection-start-column="4" selection-end-line="24" selection-end-column="4" /> + <state vertical-scroll-proportion="1.4663073"> + <caret line="109" column="16" selection-start-line="109" selection-start-column="16" selection-end-line="109" selection-end-column="16" /> + <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/scripts/magdata/magcreator/create_array_sphere_disc_slab.py"> + <entry file="file://$PROJECT_DIR$/pyramid/diagnostics.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.68609864"> - <caret line="36" column="0" selection-start-line="36" selection-start-column="0" selection-end-line="36" selection-end-column="0" /> + <state vertical-scroll-proportion="0.29784366"> + <caret line="13" column="23" selection-start-line="13" selection-start-column="23" selection-end-line="13" selection-end-column="23" /> <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/setup.py"> + <entry file="file://$PROJECT_DIR$/pyramid/kernel.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="13" column="0" selection-start-line="13" selection-start-column="0" selection-end-line="13" selection-end-column="0" /> + <state vertical-scroll-proportion="-2.6060605"> + <caret line="4" column="0" selection-start-line="4" selection-start-column="0" selection-end-line="4" selection-end-column="0" /> <folding /> </state> </provider> </entry> - <entry file="file://$APPLICATION_HOME_DIR$/helpers/pydev/pydevconsole.py"> + <entry file="file://$PROJECT_DIR$/pyramid/fft.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.4069641"> - <caret line="22" column="0" selection-start-line="22" selection-start-column="0" selection-end-line="22" selection-end-column="0" /> + <state vertical-scroll-proportion="0.41322315"> + <caret line="227" column="0" selection-start-line="227" selection-start-column="0" selection-end-line="227" selection-end-column="0" /> + <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyramid/dataset.py"> + <entry file="file://$PROJECT_DIR$/pyramid/version.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="8" column="0" selection-start-line="8" selection-start-column="0" selection-end-line="8" selection-end-column="0" /> + <state vertical-scroll-proportion="0.0945758"> + <caret line="4" column="0" selection-start-line="4" selection-start-column="0" selection-end-line="4" selection-end-column="0" /> <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyramid/diagnostics.py"> + <entry file="file://$PROJECT_DIR$/setup.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="127" column="34" selection-start-line="127" selection-start-column="34" selection-end-line="127" selection-end-column="34" /> - <folding> - <element signature="e#261#279#0" expanded="false" /> - </folding> + <state vertical-scroll-proportion="0.32962447"> + <caret line="103" column="0" selection-start-line="103" selection-start-column="0" selection-end-line="103" selection-end-column="0" /> + <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyramid/analytic.py"> + <entry file="file://$PROJECT_DIR$/pyramid/phasemapper.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="12" column="0" selection-start-line="12" selection-start-column="0" selection-end-line="12" selection-end-column="0" /> + <state vertical-scroll-proportion="0.6334232"> + <caret line="598" column="65" selection-start-line="598" selection-start-column="65" selection-end-line="598" selection-end-column="65" /> <folding /> </state> </provider> </entry> - <entry file="file://C:/Anaconda2/Lib/site-packages/traits/traits.py"> + <entry file="file://$PROJECT_DIR$/pyramid/tests/test_dataset.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="488" column="0" selection-start-line="488" selection-start-column="0" selection-end-line="488" selection-end-column="0" /> + <state vertical-scroll-proportion="0.17097701"> + <caret line="7" column="0" selection-start-line="7" selection-start-column="0" selection-end-line="7" selection-end-column="0" /> + <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/../HyperSpy/hyperspy/gui/tools.py"> + <entry file="file://$PROJECT_DIR$/pyramid/dataset.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.22198041"> - <caret line="691" column="39" selection-start-line="691" selection-start-column="39" selection-end-line="691" selection-end-column="39" /> + <state vertical-scroll-proportion="0.024425287"> + <caret line="28" column="66" selection-start-line="28" selection-start-column="62" selection-end-line="28" selection-end-column="66" /> + <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/../HyperSpy/hyperspy/drawing/image.py"> + <entry file="file://$PROJECT_DIR$/pyramid/tests/test_phasemap.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.33297062"> - <caret line="29" column="41" selection-start-line="29" selection-start-column="41" selection-end-line="29" selection-end-column="41" /> + <state vertical-scroll-proportion="0.21982759"> + <caret line="9" column="37" selection-start-line="9" selection-start-column="37" selection-end-line="9" selection-end-column="37" /> + <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/../HyperSpy/hyperspy/api.py"> + <entry file="file://$PROJECT_DIR$/pyramid/tests/test_magdata.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="-0.44287267"> + <state vertical-scroll-proportion="0.0"> <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> + <folding /> </state> </provider> </entry> - <entry file="file://$USER_HOME$/.PyCharm50/system/python_stubs/884504192/thread.py"> + <entry file="file://$PROJECT_DIR$/pyramid/tests/test_magcreator.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.6289445"> - <caret line="126" column="23" selection-start-line="126" selection-start-column="23" selection-end-line="126" selection-end-column="23" /> + <state vertical-scroll-proportion="0.0"> + <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> + <folding /> </state> </provider> </entry> - <entry file="file://$APPLICATION_HOME_DIR$/helpers/pydev/pydevd.py"> + <entry file="file://$PROJECT_DIR$/pyramid/tests/test_kernel.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.44396082"> - <caret line="1807" column="47" selection-start-line="1807" selection-start-column="47" selection-end-line="1807" selection-end-column="47" /> + <state vertical-scroll-proportion="0.0"> + <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> + <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyramid/tests/test_phasemapper.py"> + <entry file="file://$PROJECT_DIR$/pyramid/tests/test_forwardmodel.py"> <provider selected="true" editor-type-id="text-editor"> <state vertical-scroll-proportion="0.0"> - <caret line="2" column="0" selection-start-line="2" selection-start-column="0" selection-end-line="2" selection-end-column="0" /> + <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> <folding /> </state> </provider> </entry> - <entry file="file://C:/Anaconda2/Lib/site-packages/pyface/qt/__init__.py"> + <entry file="file://$PROJECT_DIR$/pyramid/tests/test_costfunction.py"> <provider selected="true" editor-type-id="text-editor"> <state vertical-scroll-proportion="0.0"> - <caret line="30" column="23" selection-start-line="30" selection-start-column="23" selection-end-line="30" selection-end-column="23" /> + <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyramid/__init__.py"> + <entry file="file://$PROJECT_DIR$/pyramid/tests/test_phasemapper.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="57" column="0" selection-start-line="57" selection-start-column="0" selection-end-line="57" selection-end-column="0" /> + <state vertical-scroll-proportion="0.47304583"> + <caret line="159" column="21" selection-start-line="159" selection-start-column="21" selection-end-line="159" selection-end-column="21" /> <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyramid/phasemap.py"> + <entry file="file://$PROJECT_DIR$/pyramid/tests/test_projector.py"> <provider selected="true" editor-type-id="text-editor"> <state vertical-scroll-proportion="0.0"> - <caret line="331" column="45" selection-start-line="331" selection-start-column="45" selection-end-line="331" selection-end-column="45" /> + <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/scripts/gui/phasemap_creator.py"> + <entry file="file://$PROJECT_DIR$/pyramid/tests/test_regularisator.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="260" column="58" selection-start-line="260" selection-start-column="58" selection-end-line="260" selection-end-column="58" /> + <state vertical-scroll-proportion="-1.9097035"> + <caret line="17" column="0" selection-start-line="17" selection-start-column="0" selection-end-line="17" selection-end-column="0" /> <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyramid/colormap.py"> + <entry file="file://$PROJECT_DIR$/pyramid/tests/test_analytic.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="243" column="32" selection-start-line="243" selection-start-column="32" selection-end-line="243" selection-end-column="32" /> + <state vertical-scroll-proportion="0.43530998"> + <caret line="19" column="16" selection-start-line="19" selection-start-column="16" selection-end-line="19" selection-end-column="16" /> <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/docs/pyramid.numcore.rst"> + <entry file="file://$PROJECT_DIR$/pyramid/numcore/phasemapper_core.c"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="9" column="0" selection-start-line="9" selection-start-column="0" selection-end-line="9" selection-end-column="0" /> + <state vertical-scroll-proportion="-5.7277627"> + <caret line="2" column="24" selection-start-line="2" selection-start-column="24" selection-end-line="2" selection-end-column="24" /> <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyramid/magdata.py"> + <entry file="file://$PROJECT_DIR$/scripts/gui/mag_slicer.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="221" column="21" selection-start-line="221" selection-start-column="21" selection-end-line="221" selection-end-column="21" /> + <state vertical-scroll-proportion="0.32210243"> + <caret line="167" column="50" selection-start-line="167" selection-start-column="50" selection-end-line="167" selection-end-column="50" /> <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/../Publications/paper 2/paper2_part3_experiment.py"> + <entry file="file://$PROJECT_DIR$/pyramid/config.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="12" column="0" selection-start-line="12" selection-start-column="0" selection-end-line="12" selection-end-column="0" /> + <state vertical-scroll-proportion="0.4811321"> + <caret line="21" column="0" selection-start-line="21" selection-start-column="0" selection-end-line="21" selection-end-column="0" /> <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/../Publications/nanowire_z_angle.py"> + <entry file="file://$PROJECT_DIR$/pyramid/__init__.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.0"> - <caret line="18" column="37" selection-start-line="18" selection-start-column="37" selection-end-line="18" selection-end-column="37" /> + <state vertical-scroll-proportion="0.1522911"> + <caret line="65" column="25" selection-start-line="65" selection-start-column="25" selection-end-line="65" selection-end-column="25" /> <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/../Publications/pico 2015/poster_pico2015_2d.py"> + <entry file="file://$PROJECT_DIR$/scripts/reconstruction/reconstruction_3d_from_magdata.py"> + <provider selected="true" editor-type-id="text-editor"> + <state vertical-scroll-proportion="0.25202155"> + <caret line="11" column="29" selection-start-line="11" selection-start-column="29" selection-end-line="11" selection-end-column="29" /> + <folding /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/pyramid/analytic.py"> <provider selected="true" editor-type-id="text-editor"> - <state vertical-scroll-proportion="0.44790256"> - <caret line="36" column="62" selection-start-line="36" selection-start-column="62" selection-end-line="36" selection-end-column="62" /> + <state vertical-scroll-proportion="0.9541779"> + <caret line="215" column="31" selection-start-line="215" selection-start-column="31" selection-end-line="215" selection-end-column="31" /> <folding /> </state> </provider> @@ -1226,13 +1220,14 @@ </component> <component name="hg4idea.settings"> <option name="CHECK_INCOMING_OUTGOING" value="true" /> - <option name="RECENT_HG_ROOT_PATH" value="$PROJECT_DIR$/../Publications" /> + <option name="RECENT_HG_ROOT_PATH" value="$PROJECT_DIR$" /> <option name="ROOT_SYNC" value="DONT_SYNC" /> </component> <component name="masterDetails"> <states> <state key="ScopeChooserConfigurable.UI"> <settings> + <last-edited>*.c</last-edited> <splitter-proportions> <option name="proportions"> <list> @@ -1240,6 +1235,10 @@ </list> </option> </splitter-proportions> + <order> + <scope name="__init__" /> + <scope name="*.c" /> + </order> </settings> </state> </states> diff --git a/docs/Makefile b/docs/Makefile index d0ca09c..a1aae98 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -7,6 +7,11 @@ SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter @@ -14,8 +19,7 @@ ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext - +.PHONY: help help: @echo "Please use \`make <target>' where <target> is one of" @echo " html to make standalone HTML files" @@ -25,76 +29,101 @@ help: @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" +.PHONY: clean clean: - -rm -rf $(BUILDDIR)/* + rm -rf $(BUILDDIR)/* +.PHONY: html html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." +.PHONY: dirhtml dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." +.PHONY: singlehtml singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." +.PHONY: pickle pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." +.PHONY: json json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." +.PHONY: htmlhelp htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." +.PHONY: qthelp qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pyramid.qhcp" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Pyramid.qhcp" @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pyramid.qhc" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Pyramid.qhc" +.PHONY: applehelp +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +.PHONY: devhelp devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/pyramid" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pyramid" + @echo "# mkdir -p $$HOME/.local/share/devhelp/Pyramid" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Pyramid" @echo "# devhelp" +.PHONY: epub epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." +.PHONY: latex latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @@ -102,22 +131,33 @@ latex: @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." +.PHONY: latexpdf latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." +.PHONY: latexpdfja +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: text text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." +.PHONY: man man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." +.PHONY: texinfo texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @@ -125,35 +165,52 @@ texinfo: @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." +.PHONY: info info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." +.PHONY: gettext gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." +.PHONY: changes changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." +.PHONY: linkcheck linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." +.PHONY: doctest doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." -pdf: - $(SPHINXBUILD) -b pdf $(ALLSPHINXOPTS) _build/pdf +.PHONY: coverage +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +.PHONY: xml +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +.PHONY: pseudoxml +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml @echo - @echo "Build finished. The PDF files are in _build/pdf." - \ No newline at end of file + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/docs/conf.py b/docs/conf.py index cf56693..133966c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,385 +1,432 @@ -# -*- coding: utf-8 -*- -# -# pyramid documentation build configuration file, created by -# sphinx-quickstart on Tue Aug 20 12:15:35 2013. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath('C:\Users\Jan\Home\PhD Thesis\Pyramid')) - -# -- General configuration ----------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinx.ext.autosummary', - 'rst2pdf.pdfbuilder', 'numpydoc'] - -numpydoc_show_class_members = False - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'pyramid' -copyright = u'2013, Jan Caron' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '' -# The full version, including alpha/beta/rc tags. -release = '' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ['_build'] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'sphinxdoc' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# "<project> v<release> documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -html_logo = 'Pyramid Logo.png' - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -html_favicon = 'icon.ico' - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a <link> tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'pyramiddoc' - - -# -- Options for LaTeX output -------------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'pyramid.tex', u'pyramid Documentation', - u'Jan Caron', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'pyramid', u'pyramid Documentation', - [u'Jan Caron'], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------------ - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'pyramid', u'pyramid Documentation', - u'Jan Caron', 'pyramid', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' - - -# -- Options for Epub output --------------------------------------------------- - -# Bibliographic Dublin Core info. -epub_title = u'Pyramid' -epub_author = u'Jan Caron' -epub_publisher = u'Jan Caron' -epub_copyright = u'2013, Jan Caron' - -# The language of the text. It defaults to the language option -# or en if the language is not set. -#epub_language = '' - -# The scheme of the identifier. Typical schemes are ISBN or URL. -#epub_scheme = '' - -# The unique identifier of the text. This can be a ISBN number -# or the project homepage. -#epub_identifier = '' - -# A unique identification for the text. -#epub_uid = '' - -# A tuple containing the cover image and cover page html template filenames. -#epub_cover = () - -# HTML files that should be inserted before the pages created by sphinx. -# The format is a list of tuples containing the path and title. -#epub_pre_files = [] - -# HTML files shat should be inserted after the pages created by sphinx. -# The format is a list of tuples containing the path and title. -#epub_post_files = [] - -# A list of files that should not be packed into the epub file. -#epub_exclude_files = [] - -# The depth of the table of contents in toc.ncx. -#epub_tocdepth = 3 - -# Allow duplicate toc entries. -#epub_tocdup = True - -# -- Options for PDF output -------------------------------------------------- -# Grouping the document tree into PDF files. List of tuples -# (source start file, target name, title, author, options). -# -# If there is more than one author, separate them with \\. -# For example: r'Guido van Rossum\\Fred L. Drake, Jr., editor' -# -# The options element is a dictionary that lets you override -# this config per-document. -# For example, -# ('index', u'MyProject', u'My Project', u'Author Name', -# dict(pdf_compressed = True)) -# would mean that specific document would be compressed -# regardless of the global pdf_compressed setting. - -pdf_documents = [ -('index', u'Pyramid', u'Pyramid', u'Jan Caron'), -] - -# A comma-separated list of custom stylesheets. Example: -pdf_stylesheets = ['sphinx','kerning','a4'] - -# A list of folders to search for stylesheets. Example: -pdf_style_path = ['.', '_styles'] - -# Create a compressed PDF -# Use True/False or 1/0 -# Example: compressed=True -#pdf_compressed = False - -# A colon-separated list of folders to search for fonts. Example: -# pdf_font_path = ['/usr/share/fonts', '/usr/share/texmf-dist/fonts/'] - -# Language to be used for hyphenation support -#pdf_language = "en_US" - -# Mode for literal blocks wider than the frame. Can be -# overflow, shrink or truncate -#pdf_fit_mode = "shrink" - -# Section level that forces a break page. -# For example: 1 means top-level sections start in a new page -# 0 means disabled -#pdf_break_level = 0 - -# When a section starts in a new page, force it to be 'even', 'odd', -# or just use 'any' -#pdf_breakside = 'any' - -# Insert footnotes where they are defined instead of -# at the end. -#pdf_inline_footnotes = True - -# verbosity level. 0 1 or 2 -#pdf_verbosity = 0 - -# If false, no index is generated. -#pdf_use_index = True - -# If false, no modindex is generated. -#pdf_use_modindex = True - -# If false, no coverpage is generated. -#pdf_use_coverpage = True - -# Name of the cover page template to use -#pdf_cover_template = 'sphinxcover.tmpl' - -# Documents to append as an appendix to all manuals. -#pdf_appendices = [] - -# Enable experimental feature to split table cells. Use it -# if you get "DelayedTable too big" errors -#pdf_splittables = False - -# Set the default DPI for images -#pdf_default_dpi = 72 - -# Enable rst2pdf extension modules (default is only vectorpdf) -# you need vectorpdf if you want to use sphinx's graphviz support -#pdf_extensions = ['vectorpdf'] - -# Page template name for "regular" pages -#pdf_page_template = 'cutePage' - -# Show Table Of Contents at the beginning? -#pdf_use_toc = True - -# How many levels deep should the table of contents be? -pdf_toc_depth = 9999 - -# Add section number to section references -pdf_use_numbered_links = False - -# Background images fitting mode -pdf_fit_background_mode = 'scale' +# -*- coding: utf-8 -*- +# +# Pyramid documentation build configuration file, created by +# sphinx-quickstart on Thu Feb 25 19:34:18 2016. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.intersphinx', + 'sphinx.ext.mathjax', + 'sphinx.ext.viewcode', + 'sphinx.ext.autosummary', + 'rst2pdf.pdfbuilder', + 'numpydoc'] + +numpydoc_show_class_members = False + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Pyramid' +copyright = u'2016, Jan Caron' +author = u'Jan Caron' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = u'' +# The full version, including alpha/beta/rc tags. +release = u'' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +# keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'sphinxdoc' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +# html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +html_logo = 'icon.ico' + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +html_favicon = 'icon.ico' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +# html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Pyramiddoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', + + # Latex figure (float) alignment + #'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'Pyramid.tex', u'Pyramid Documentation', + u'Jan Caron', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'pyramid', u'Pyramid Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'Pyramid', u'Pyramid Documentation', + author, 'Pyramid', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'https://docs.python.org/': None} + +# -- Options for Epub output --------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = u'Pyramid' +epub_author = u'Jan Caron' +epub_publisher = u'Jan Caron' +epub_copyright = u'2013, Jan Caron' + +# The language of the text. It defaults to the language option +# or en if the language is not set. +#epub_language = '' + +# The scheme of the identifier. Typical schemes are ISBN or URL. +#epub_scheme = '' + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +#epub_identifier = '' + +# A unique identification for the text. +#epub_uid = '' + +# A tuple containing the cover image and cover page html template filenames. +#epub_cover = () + +# HTML files that should be inserted before the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_pre_files = [] + +# HTML files shat should be inserted after the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_post_files = [] + +# A list of files that should not be packed into the epub file. +#epub_exclude_files = [] + +# The depth of the table of contents in toc.ncx. +#epub_tocdepth = 3 + +# Allow duplicate toc entries. +#epub_tocdup = True + + +# -- Options for PDF output -------------------------------------------------- +# Grouping the document tree into PDF files. List of tuples +# (source start file, target name, title, author, options). +# +# If there is more than one author, separate them with \\. +# For example: r'Guido van Rossum\\Fred L. Drake, Jr., editor' +# +# The options element is a dictionary that lets you override +# this config per-document. +# For example, +# ('index', u'MyProject', u'My Project', u'Author Name', +# dict(pdf_compressed = True)) +# would mean that specific document would be compressed +# regardless of the global pdf_compressed setting. + +pdf_documents = [ +('index', u'Pyramid', u'Pyramid', u'Jan Caron'), +] + +# A comma-separated list of custom stylesheets. Example: +pdf_stylesheets = ['sphinx','kerning','a4'] + +# A list of folders to search for stylesheets. Example: +pdf_style_path = ['.', '_styles'] + +# Create a compressed PDF +# Use True/False or 1/0 +# Example: compressed=True +#pdf_compressed = False + +# A colon-separated list of folders to search for fonts. Example: +# pdf_font_path = ['/usr/share/fonts', '/usr/share/texmf-dist/fonts/'] + +# Language to be used for hyphenation support +#pdf_language = "en_US" + +# Mode for literal blocks wider than the frame. Can be +# overflow, shrink or truncate +#pdf_fit_mode = "shrink" + +# Section level that forces a break page. +# For example: 1 means top-level sections start in a new page +# 0 means disabled +#pdf_break_level = 0 + +# When a section starts in a new page, force it to be 'even', 'odd', +# or just use 'any' +#pdf_breakside = 'any' + +# Insert footnotes where they are defined instead of +# at the end. +#pdf_inline_footnotes = True + +# verbosity level. 0 1 or 2 +#pdf_verbosity = 0 + +# If false, no index is generated. +#pdf_use_index = True + +# If false, no modindex is generated. +#pdf_use_modindex = True + +# If false, no coverpage is generated. +#pdf_use_coverpage = True + +# Name of the cover page template to use +#pdf_cover_template = 'sphinxcover.tmpl' + +# Documents to append as an appendix to all manuals. +#pdf_appendices = [] + +# Enable experimental feature to split table cells. Use it +# if you get "DelayedTable too big" errors +#pdf_splittables = False + +# Set the default DPI for images +#pdf_default_dpi = 72 + +# Enable rst2pdf extension modules (default is only vectorpdf) +# you need vectorpdf if you want to use sphinx's graphviz support +#pdf_extensions = ['vectorpdf'] + +# Page template name for "regular" pages +#pdf_page_template = 'cutePage' + +# Show Table Of Contents at the beginning? +#pdf_use_toc = True + +# How many levels deep should the table of contents be? +pdf_toc_depth = 9999 + +# Add section number to section references +pdf_use_numbered_links = False + +# Background images fitting mode +pdf_fit_background_mode = 'scale' diff --git a/docs/index.rst b/docs/index.rst index 9641203..08f0e46 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,23 +1,23 @@ -.. pyramid documentation master file, created by - sphinx-quickstart on Tue Aug 20 12:15:35 2013. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to pyramid's documentation! -=================================== - -Contents: - -.. toctree:: - :maxdepth: 4 - - pyramid - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - +.. Pyramid documentation master file, created by +sphinx-quickstart on Thu Feb 25 19:34:18 2016. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to Pyramid's documentation! +=================================== + +Contents: + +.. toctree:: + :maxdepth: 4 + + pyramid + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/docs/make.bat b/docs/make.bat index 7a09652..670e29f 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -1,197 +1,263 @@ -@ECHO OFF - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set BUILDDIR=_build -set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . -set I18NSPHINXOPTS=%SPHINXOPTS% . -if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% - set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% -) - -if "%1" == "" goto help - -if "%1" == "help" ( - :help - echo.Please use `make ^<target^>` where ^<target^> is one of - echo. html to make standalone HTML files - echo. dirhtml to make HTML files named index.html in directories - echo. singlehtml to make a single large HTML file - echo. pickle to make pickle files - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. devhelp to make HTML files and a Devhelp project - echo. epub to make an epub - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. text to make text files - echo. man to make manual pages - echo. texinfo to make Texinfo files - echo. gettext to make PO message catalogs - echo. changes to make an overview over all changed/added/deprecated items - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - goto end -) - -if "%1" == "clean" ( - for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i - del /q /s %BUILDDIR%\* - goto end -) - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/html. - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. - goto end -) - -if "%1" == "singlehtml" ( - %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the pickle files. - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the JSON files. - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in %BUILDDIR%/htmlhelp. - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\pyramid.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\pyramid.ghc - goto end -) - -if "%1" == "devhelp" ( - %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. - goto end -) - -if "%1" == "epub" ( - %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The epub file is in %BUILDDIR%/epub. - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "text" ( - %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The text files are in %BUILDDIR%/text. - goto end -) - -if "%1" == "man" ( - %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The manual pages are in %BUILDDIR%/man. - goto end -) - -if "%1" == "texinfo" ( - %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. - goto end -) - -if "%1" == "gettext" ( - %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The message catalogs are in %BUILDDIR%/locale. - goto end -) - -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes - if errorlevel 1 exit /b 1 - echo. - echo.The overview file is in %BUILDDIR%/changes. - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck - if errorlevel 1 exit /b 1 - echo. - echo.Link check complete; look for any errors in the above output ^ -or in %BUILDDIR%/linkcheck/output.txt. - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest - if errorlevel 1 exit /b 1 - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in %BUILDDIR%/doctest/output.txt. - goto end -) - -if "%1" == "pdf" ( - %SPHINXBUILD% -b pdf %ALLSPHINXOPTS% %BUILDDIR%/pdf - echo. - echo.Build finished. The PDF files are in %BUILDDIR%/pdf - goto end -) - -:end +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^<target^>` where ^<target^> is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + echo. coverage to run coverage check of the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +REM Check if sphinx-build is available and fallback to Python version if any +%SPHINXBUILD% 1>NUL 2>NUL +if errorlevel 9009 goto sphinx_python +goto sphinx_ok + +:sphinx_python + +set SPHINXBUILD=python -m sphinx.__init__ +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +:sphinx_ok + + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Pyramid.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Pyramid.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "coverage" ( + %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage + if errorlevel 1 exit /b 1 + echo. + echo.Testing of coverage in the sources finished, look at the ^ +results in %BUILDDIR%/coverage/python.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/docs/pyramid.rst b/docs/pyramid.rst index bbf5715..d91ce9f 100644 --- a/docs/pyramid.rst +++ b/docs/pyramid.rst @@ -9,6 +9,14 @@ pyramid Package :show-inheritance: :special-members: +:mod:`colormap` Module +-------------------------- + +.. automodule:: pyramid.colormap +:members: + :show-inheritance: + :special-members: + :mod:`costfunction` Module -------------------------- @@ -25,6 +33,22 @@ pyramid Package :show-inheritance: :special-members: +:mod:`diagnostics` Module +-------------------------- + +.. automodule:: pyramid.diagnostics +:members: + :show-inheritance: + :special-members: + +:mod:`fft` Module +-------------------------- + +.. automodule:: pyramid.fft +:members: + :show-inheritance: + :special-members: + :mod:`forwardmodel` Module -------------------------- @@ -57,14 +81,6 @@ pyramid Package :show-inheritance: :special-members: -:mod:`reconstruction` Module ----------------------------- - -.. automodule:: pyramid.reconstruction - :members: - :show-inheritance: - :special-members: - :mod:`phasemap` Module ---------------------- @@ -85,6 +101,38 @@ pyramid Package ----------------------- .. automodule:: pyramid.projector +:members: + :show-inheritance: + :special-members: + +:mod:`quaternion` Module +---------------------------- + +.. automodule:: pyramid.quaternion +:members: + :show-inheritance: + :special-members: + +:mod:`ramp` Module +---------------------------- + +.. automodule:: pyramid.ramp +:members: + :show-inheritance: + :special-members: + +:mod:`reconstruction` Module +---------------------------- + +.. automodule:: pyramid.reconstruction +:members: + :show-inheritance: + :special-members: + +:mod:`regularisator` Module +---------------------------- + +.. automodule:: pyramid.regularisator :members: :show-inheritance: :special-members: diff --git a/pyramid/__init__.py b/pyramid/__init__.py index 33fe22e..4f5ffe1 100644 --- a/pyramid/__init__.py +++ b/pyramid/__init__.py @@ -47,14 +47,45 @@ numcore Provides fast numerical functions for core routines. """ -import logging +import logging _log = logging.getLogger(__name__) try: # Try importing HyperSpy (here because otherwise API Errors might occur): import hyperspy.api except ImportError: _log.error('Could not load hyperspy package!') +from . import analytic +from . import magcreator +from . import reconstruction +from . import fft +from . import costfunction +from .costfunction import * +from . import dataset +from .dataset import * +from . import diagnostics +from .diagnostics import * +from . import forwardmodel +from .forwardmodel import * +from . import kernel +from .kernel import * +from . import magdata +from .magdata import * +from . import phasemap +from .phasemap import * +from . import phasemapper +from .phasemapper import * +from . import projector +from .projector import * +from . import regularisator +from .regularisator import * +from . import ramp +from .ramp import * +from . import quaternion +from .quaternion import * +from . import colormap +from .colormap import * +from .config import * from .version import version as __version__ from .version import hg_revision as __hg_revision__ diff --git a/pyramid/analytic.py b/pyramid/analytic.py index e7ee296..d0f879c 100644 --- a/pyramid/analytic.py +++ b/pyramid/analytic.py @@ -10,15 +10,13 @@ calculated by the functions from the :mod:`~pyramid.phasemapper` module. """ +import logging import numpy as np from numpy import pi from pyramid.phasemap import PhaseMap -import logging - - __all__ = ['phase_mag_slab', 'phase_mag_slab', 'phase_mag_sphere', 'phase_mag_vortex'] _log = logging.getLogger(__name__) @@ -26,7 +24,7 @@ PHI_0 = 2067.83 # magnetic flux in T*nm² def phase_mag_slab(dim, a, phi, center, width, b_0=1): - '''Calculate the analytic magnetic phase for a homogeneously magnetized slab. + """Calculate the analytic magnetic phase for a homogeneously magnetized slab. Parameters ---------- @@ -49,39 +47,41 @@ def phase_mag_slab(dim, a, phi, center, width, b_0=1): phase_map : :class:`~numpy.ndarray` (N=2) The phase as a 2-dimensional array. - ''' + """ _log.debug('Calling phase_mag_slab') # Function for the phase: - def phi_mag(x, y): - def F_0(x, y): - A = np.log(x**2 + y**2 + 1E-30) - B = np.arctan(x / (y+1E-30)) - return x*A - 2*x + 2*y*B - return coeff * Lz * (- np.cos(phi) * (F_0(x-x0-Lx/2, y-y0-Ly/2) - - F_0(x-x0+Lx/2, y-y0-Ly/2) - - F_0(x-x0-Lx/2, y-y0+Ly/2) - + F_0(x-x0+Lx/2, y-y0+Ly/2)) - + np.sin(phi) * (F_0(y-y0-Ly/2, x-x0-Lx/2) - - F_0(y-y0+Ly/2, x-x0-Lx/2) - - F_0(y-y0-Ly/2, x-x0+Lx/2) - + F_0(y-y0+Ly/2, x-x0+Lx/2))) + def _phi_mag(x, y): + def _F_0(x, y): + A = np.log(x ** 2 + y ** 2 + 1E-30) + B = np.arctan(x / (y + 1E-30)) + return x * A - 2 * x + 2 * y * B + + return coeff * Lz * (- np.cos(phi) * (_F_0(x - x0 - Lx / 2, y - y0 - Ly / 2) - + _F_0(x - x0 + Lx / 2, y - y0 - Ly / 2) - + _F_0(x - x0 - Lx / 2, y - y0 + Ly / 2) + + _F_0(x - x0 + Lx / 2, y - y0 + Ly / 2)) + + np.sin(phi) * (_F_0(y - y0 - Ly / 2, x - x0 - Lx / 2) - + _F_0(y - y0 + Ly / 2, x - x0 - Lx / 2) - + _F_0(y - y0 - Ly / 2, x - x0 + Lx / 2) + + _F_0(y - y0 + Ly / 2, x - x0 + Lx / 2))) + # Process input parameters: z_dim, y_dim, x_dim = dim y0 = a * center[1] # y0, x0 define the center of a pixel, x0 = a * center[2] # hence: (cellindex + 0.5) * grid spacing Lz, Ly, Lx = a * width[0], a * width[1], a * width[2] - coeff = - b_0 / (4*PHI_0) # Minus because of negative z-direction + coeff = - b_0 / (4 * PHI_0) # Minus because of negative z-direction # Create grid: - x = np.linspace(a/2, x_dim*a-a/2, num=x_dim) - y = np.linspace(a/2, y_dim*a-a/2, num=y_dim) + x = np.linspace(a / 2, x_dim * a - a / 2, num=x_dim) + y = np.linspace(a / 2, y_dim * a - a / 2, num=y_dim) xx, yy = np.meshgrid(x, y) # Return phase: - return PhaseMap(a, phi_mag(xx, yy)) + return PhaseMap(a, _phi_mag(xx, yy)) def phase_mag_disc(dim, a, phi, center, radius, height, b_0=1): - '''Calculate the analytic magnetic phase for a homogeneously magnetized disc. + """Calculate the analytic magnetic phase for a homogeneously magnetized disc. Parameters ---------- @@ -106,14 +106,14 @@ def phase_mag_disc(dim, a, phi, center, radius, height, b_0=1): phase_map : :class:`~numpy.ndarray` (N=2) The phase as a 2-dimensional array. - ''' + """ _log.debug('Calling phase_mag_disc') # Function for the phase: - def phi_mag(x, y): - r = np.hypot(x-x0, y-y0) - result = coeff * Lz * ((y-y0) * np.cos(phi) - (x-x0) * np.sin(phi)) - result *= np.where(r <= R, 1, (R / (r+1E-30)) ** 2) + def _phi_mag(x, y): + r = np.hypot(x - x0, y - y0) + result = coeff * Lz * ((y - y0) * np.cos(phi) - (x - x0) * np.sin(phi)) + result *= np.where(r <= R, 1, (R / (r + 1E-30)) ** 2) return result # Process input parameters: @@ -122,17 +122,17 @@ def phase_mag_disc(dim, a, phi, center, radius, height, b_0=1): x0 = a * center[2] Lz = a * height R = a * radius - coeff = pi * b_0 / (2*PHI_0) # Minus is gone because of negative z-direction + coeff = pi * b_0 / (2 * PHI_0) # Minus is gone because of negative z-direction # Create grid: - x = np.linspace(a/2, x_dim*a-a/2, num=x_dim) - y = np.linspace(a/2, y_dim*a-a/2, num=y_dim) + x = np.linspace(a / 2, x_dim * a - a / 2, num=x_dim) + y = np.linspace(a / 2, y_dim * a - a / 2, num=y_dim) xx, yy = np.meshgrid(x, y) # Return phase: - return PhaseMap(a, phi_mag(xx, yy)) + return PhaseMap(a, _phi_mag(xx, yy)) def phase_mag_sphere(dim, a, phi, center, radius, b_0=1): - '''Calculate the analytic magnetic phase for a homogeneously magnetized sphere. + """Calculate the analytic magnetic phase for a homogeneously magnetized sphere. Parameters ---------- @@ -155,13 +155,14 @@ def phase_mag_sphere(dim, a, phi, center, radius, b_0=1): phase_map : :class:`~numpy.ndarray` (N=2) The phase as a 2-dimensional array. - ''' + """ _log.debug('Calling phase_mag_sphere') # Function for the phase: - def phi_mag(x, y): - r = np.hypot(x-x0, y-y0) - result = coeff * R ** 3 / (r+1E-30) ** 2 * ((y-y0) * np.cos(phi) - (x-x0) * np.sin(phi)) + def _phi_mag(x, y): + r = np.hypot(x - x0, y - y0) + result = coeff * R ** 3 / (r + 1E-30) ** 2 * ( + (y - y0) * np.cos(phi) - (x - x0) * np.sin(phi)) result *= np.where(r > R, 1, (1 - (1 - (r / R) ** 2) ** (3. / 2.))) return result @@ -170,17 +171,17 @@ def phase_mag_sphere(dim, a, phi, center, radius, b_0=1): y0 = a * center[1] x0 = a * center[2] R = a * radius - coeff = 2./3. * pi * b_0 / PHI_0 # Minus is gone because of negative z-direction + coeff = 2. / 3. * pi * b_0 / PHI_0 # Minus is gone because of negative z-direction # Create grid: x = np.linspace(a / 2, x_dim * a - a / 2, num=x_dim) y = np.linspace(a / 2, y_dim * a - a / 2, num=y_dim) xx, yy = np.meshgrid(x, y) # Return phase: - return PhaseMap(a, phi_mag(xx, yy)) + return PhaseMap(a, _phi_mag(xx, yy)) def phase_mag_vortex(dim, a, center, radius, height, b_0=1): - '''Calculate the analytic magnetic phase for a vortex state disc. + """Calculate the analytic magnetic phase for a vortex state disc. Parameters ---------- @@ -203,11 +204,11 @@ def phase_mag_vortex(dim, a, center, radius, height, b_0=1): phase_map : :class:`~numpy.ndarray` (N=2) The phase as a 2-dimensional array. - ''' + """ _log.debug('Calling phase_mag_vortex') # Function for the phase: - def phi_mag(x, y): + def _phi_mag(x, y): r = np.hypot(x - x0, y - y0) result = coeff * np.where(r <= R, r - R, 0) return result @@ -220,8 +221,8 @@ def phase_mag_vortex(dim, a, center, radius, height, b_0=1): R = a * radius coeff = - pi * b_0 * Lz / PHI_0 # Minus because of negative z-direction # Create grid: - x = np.linspace(a/2, x_dim*a-a/2, num=x_dim) - y = np.linspace(a/2, y_dim*a-a/2, num=y_dim) + x = np.linspace(a / 2, x_dim * a - a / 2, num=x_dim) + y = np.linspace(a / 2, y_dim * a - a / 2, num=y_dim) xx, yy = np.meshgrid(x, y) # Return phase: - return PhaseMap(a, phi_mag(xx, yy)) + return PhaseMap(a, _phi_mag(xx, yy)) diff --git a/pyramid/colormap.py b/pyramid/colormap.py index 42ce0db..55543fa 100644 --- a/pyramid/colormap.py +++ b/pyramid/colormap.py @@ -8,21 +8,20 @@ additional functions and can encode three-dimensional directions.""" import logging from numbers import Number -import matplotlib as mpl import matplotlib.pyplot as plt import numpy as np from PIL import Image +from matplotlib import colors __all__ = ['DirectionalColormap', 'TransparentColormap'] -class DirectionalColormap(mpl.colors.LinearSegmentedColormap): - - '''Colormap subclass for encoding 3D-directions with colors. +class DirectionalColormap(colors.LinearSegmentedColormap): + """Colormap subclass for encoding 3D-directions with colors. This class is a subclass of the :class:`~matplotlib.pyplot.colors.LinearSegmentedColormap` class with a few classmethods which can be used for convenience. The - :method:`.display_colorwheel` method can be used to display a colorhweel which is used for + :func:`.display_colorwheel` method can be used to display a colorhweel which is used for the directional encoding and three `rgb_from_...` methods are used to calculate rgb tuples from 3D-directions, angles or directly from a colorindex and a saturation value. This is useful for quiverplots where the arrow colors can be set individually by providing said rgb- @@ -38,9 +37,9 @@ class DirectionalColormap(mpl.colors.LinearSegmentedColormap): Flag which is used to invert the internal colormap (default is False). Just influences the classical use as a normal colormap, not the classmethods! - ''' + """ - _log = logging.getLogger(__name__+'.DirectionalColormap') + _log = logging.getLogger(__name__ + '.DirectionalColormap') CDICT = {'red': [(0.00, 0.0, 0.0), (0.25, 1.0, 1.0), @@ -78,18 +77,18 @@ class DirectionalColormap(mpl.colors.LinearSegmentedColormap): (0.75, 0.0, 0.0), (1.00, 1.0, 1.0)]} - HOLO_CMAP = mpl.colors.LinearSegmentedColormap('my_colormap', CDICT, 256) - HOLO_CMAP_INV = mpl.colors.LinearSegmentedColormap('my_colormap', CDICT_INV, 256) + HOLO_CMAP = colors.LinearSegmentedColormap('my_colormap', CDICT, 256) + HOLO_CMAP_INV = colors.LinearSegmentedColormap('my_colormap', CDICT_INV, 256) def __init__(self, inverted=False): self._log.debug('Calling __create_directional_colormap') cdict = self.CDICT_INV if inverted else self.CDICT super(DirectionalColormap, self).__init__('directional_colormap', cdict, N=256) - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) @classmethod def display_colorwheel(cls, mode='white_to_color'): - '''Display a color wheel to illustrate the color coding of the gradient direction. + """Display a color wheel to illustrate the color coding of the gradient direction. Parameters ---------- @@ -101,12 +100,12 @@ class DirectionalColormap(mpl.colors.LinearSegmentedColormap): ------- None - ''' + """ cls._log.debug('Calling display_color_wheel') yy, xx = np.indices((512, 512)) - 256 r = np.hypot(xx, yy) # Create the wheel: - colorind = (1 + np.arctan2(yy, xx)/np.pi) / 2 + colorind = (1 + np.arctan2(yy, xx) / np.pi) / 2 saturation = r / 256 # 0 in center, 1 at borders of circle! if mode == 'black_to_color': pass # no further modification necessary! @@ -115,7 +114,7 @@ class DirectionalColormap(mpl.colors.LinearSegmentedColormap): elif mode == 'white_to_color': saturation = 2 - saturation elif mode == 'white_to_color_to_black': - saturation = 2 - 2*saturation + saturation = 2 - 2 * saturation else: raise Exception('Invalid color wheel mode!') saturation *= np.where(r <= 256, 1, 0) # Cut out the wheel! @@ -130,7 +129,7 @@ class DirectionalColormap(mpl.colors.LinearSegmentedColormap): @classmethod def rgb_from_colorind_and_saturation(cls, colorind, saturation): - '''Construct a rgb tuple from a colorindex and a saturation value. + """Construct a rgb tuple from a colorindex and a saturation value. Parameters ---------- @@ -154,19 +153,19 @@ class DirectionalColormap(mpl.colors.LinearSegmentedColormap): ----- Also works with numpy arrays as input! Always returns array of shape (..., 3)! - ''' + """ cls._log.debug('Calling rgb_from_colorind_and_saturation') # Make sure colorind and saturation are arrays (if not make it so): c = np.array([colorind]) if isinstance(colorind, Number) else colorind s = np.array([saturation]) if isinstance(saturation, Number) else saturation # Calculate rgb and the inverse and combine them: rgb_norm = (np.minimum(s, np.ones_like(s)).T * cls.HOLO_CMAP(c)[..., :3].T).T - rgb_invs = (np.maximum(s-1, np.zeros_like(s)).T * cls.HOLO_CMAP_INV(c)[..., :3].T).T - return (255.999 * (rgb_norm + rgb_invs)).astype(np.uint8) + rgb_invs = (np.maximum(s - 1, np.zeros_like(s)).T * cls.HOLO_CMAP_INV(c)[..., :3].T).T + return np.asarray(255.999 * (rgb_norm + rgb_invs), dtype=np.uint8) @classmethod - def rgb_from_angles(cls, phi, theta=np.pi/2): - '''Construct a rgb tuple from two angles representing a 3D direction. + def rgb_from_angles(cls, phi, theta=np.pi / 2): + """Construct a rgb tuple from two angles representing a 3D direction. Parameters ---------- @@ -184,15 +183,15 @@ class DirectionalColormap(mpl.colors.LinearSegmentedColormap): ----- Also works with numpy arrays as input! - ''' + """ cls._log.debug('Calling rgb_from_angles') - colorind = (1 + phi/np.pi) / 2 - saturation = 2 * (1 - theta/np.pi) # goes from 0 to 2! + colorind = (1 + phi / np.pi) / 2 + saturation = 2 * (1 - theta / np.pi) # goes from 0 to 2! return cls.rgb_from_colorind_and_saturation(colorind, saturation) @classmethod def rgb_from_direction(cls, x, y, z): - '''Construct a rgb tuple from three coordinates representing a 3D direction. + """Construct a rgb tuple from three coordinates representing a 3D direction. Parameters ---------- @@ -212,17 +211,16 @@ class DirectionalColormap(mpl.colors.LinearSegmentedColormap): ----- Also works with numpy arrays as input! - ''' + """ cls._log.debug('Calling rgb_from_direction') phi = np.arctan2(y, x) - r = np.sqrt(x**2 + y**2 + z**2) - theta = np.arccos(z / (r+1E-30)) + r = np.sqrt(x ** 2 + y ** 2 + z ** 2) + theta = np.arccos(z / (r + 1E-30)) return cls.rgb_from_angles(phi, theta) -class TransparentColormap(mpl.colors.LinearSegmentedColormap): - - '''Colormap subclass for including transparency. +class TransparentColormap(colors.LinearSegmentedColormap): + """Colormap subclass for including transparency. This class is a subclass of the :class:`~matplotlib.pyplot.colors.LinearSegmentedColormap` class with integrated support for transparency. The colormap is unicolor and varies only in @@ -239,9 +237,9 @@ class TransparentColormap(mpl.colors.LinearSegmentedColormap): alpha_range : list (N=2) of float, optional Start and end alpha value. Has to be between 0. and 1. - ''' + """ - _log = logging.getLogger(__name__+'.TransparentColormap') + _log = logging.getLogger(__name__ + '.TransparentColormap') def __init__(self, r=1., g=0., b=0., alpha_range=None): if alpha_range is None: @@ -253,4 +251,4 @@ class TransparentColormap(mpl.colors.LinearSegmentedColormap): alpha = [(0., 0., alpha_range[0]), (1., alpha_range[1], 1.)] cdict = {'red': red, 'green': green, 'blue': blue, 'alpha': alpha} super(TransparentColormap, self).__init__('transparent_colormap', cdict, N=256) - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) diff --git a/pyramid/config.py b/pyramid/config.py index 3b49a4c..82c30cf 100644 --- a/pyramid/config.py +++ b/pyramid/config.py @@ -4,18 +4,16 @@ # """Config file for the pyramid package.""" - import os - __all__ = ['DIR_PACKAGE', 'DIR_FILES', 'LOGGING_CONFIG', 'NTHREADS'] - DIR_PACKAGE = os.path.join(os.path.dirname(os.path.realpath(__file__))) DIR_FILES = os.path.abspath(os.path.join(DIR_PACKAGE, os.pardir, 'files')) LOGGING_CONFIG = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'logging.ini') try: + # noinspection PyUnresolvedReferences import multiprocessing NTHREADS = multiprocessing.cpu_count() del multiprocessing diff --git a/pyramid/costfunction.py b/pyramid/costfunction.py index e60f50a..e1d2248 100644 --- a/pyramid/costfunction.py +++ b/pyramid/costfunction.py @@ -5,20 +5,17 @@ """This module provides the :class:`~.Costfunction` class which represents a strategy to calculate the so called `cost` of a threedimensional magnetization distribution.""" +import logging import numpy as np from pyramid.regularisator import NoneRegularisator -import logging - - __all__ = ['Costfunction'] class Costfunction(object): - - '''Class for calculating the cost of a 3D magnetic distributions in relation to 2D phase maps. + """Class for calculating the cost of a 3D magnetic distributions in relation to 2D phase maps. Represents a strategy for the calculation of the `cost` of a 3D magnetic distribution in relation to two-dimensional phase maps. The `cost` is a measure for the difference of the @@ -45,9 +42,9 @@ class Costfunction(object): n: int Size of the input space. - ''' + """ - _log = logging.getLogger(__name__+'.Costfunction') + _log = logging.getLogger(__name__ + '.Costfunction') def __init__(self, fwd_model, regularisator): self._log.debug('Calling __init__') @@ -62,17 +59,17 @@ class Costfunction(object): if self.fwd_model.data_set.Se_inv is None: self.fwd_model.data_set.set_Se_inv_diag_with_conf() self.Se_inv = self.fwd_model.data_set.Se_inv - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) def __repr__(self): self._log.debug('Calling __repr__') return '%s(fwd_model=%r, regularisator=%r)' % \ - (self.__class__, self.fwd_model, self.regularisator) + (self.__class__, self.fwd_model, self.regularisator) def __str__(self): self._log.debug('Calling __str__') return 'Costfunction(fwd_model=%s, fwd_model=%s, regularisator=%s)' % \ - (self.fwd_model, self.fwd_model, self.regularisator) + (self.fwd_model, self.fwd_model, self.regularisator) def __call__(self, x): delta_y = self.fwd_model(x) - self.y @@ -82,7 +79,7 @@ class Costfunction(object): return self.chisq def init(self, x): - '''Initialise the costfunction by calculating the different cost terms. + """Initialise the costfunction by calculating the different cost terms. Parameters ---------- @@ -93,12 +90,12 @@ class Costfunction(object): ------- None - ''' + """ self._log.debug('Calling init') self(x) def jac(self, x): - '''Calculate the derivative of the costfunction for a given magnetization distribution. + """Calculate the derivative of the costfunction for a given magnetization distribution. Parameters ---------- @@ -110,13 +107,13 @@ class Costfunction(object): result : :class:`~numpy.ndarray` (N=1) Jacobi vector which represents the cost derivative of all voxels of the magnetization. - ''' + """ assert len(x) == self.n return (2 * self.fwd_model.jac_T_dot(x, self.Se_inv.dot(self.fwd_model(x) - self.y)) + self.regularisator.jac(x)) def hess_dot(self, x, vector): - '''Calculate the product of a `vector` with the Hessian matrix of the costfunction. + """Calculate the product of a `vector` with the Hessian matrix of the costfunction. Parameters ---------- @@ -133,17 +130,17 @@ class Costfunction(object): result : :class:`~numpy.ndarray` (N=1) Product of the input `vector` with the Hessian matrix of the costfunction. - ''' + """ return (2 * self.fwd_model.jac_T_dot(x, self.Se_inv.dot(self.fwd_model.jac_dot(x, vector))) + self.regularisator.hess_dot(x, vector)) def hess_diag(self, _): - ''' Return the diagonal of the Hessian. + """ Return the diagonal of the Hessian. Parameters ---------- _ : undefined Unused input - ''' + """ return np.ones(self.n) diff --git a/pyramid/dataset.py b/pyramid/dataset.py index ed721f1..c32c73e 100644 --- a/pyramid/dataset.py +++ b/pyramid/dataset.py @@ -5,26 +5,23 @@ """This module provides the :class:`~.DataSet` class for the collection of phase maps and additional data like corresponding projectors.""" +import logging +from numbers import Number +import matplotlib.pyplot as plt import numpy as np -from numbers import Number from scipy import sparse -import matplotlib.pyplot as plt +from .kernel import Kernel from .phasemap import PhaseMap from .phasemapper import PhaseMapperRDFC from .projector import Projector -from .kernel import Kernel - -import logging - __all__ = ['DataSet'] class DataSet(object): - - '''Class for collecting phase maps and corresponding projectors. + """Class for collecting phase maps and corresponding projectors. Represents a collection of (e.g. experimentally derived) phase maps, stored as :class:`~.PhaseMap` objects and corresponding projectors stored as :class:`~.Projector` @@ -38,32 +35,25 @@ class DataSet(object): The grid spacing in nm. dim: tuple (N=3) Dimensions of the 3D magnetization distribution. - phase_maps: - A list of all stored :class:`~.PhaseMap` objects. b_0: double The saturation induction in `T`. mask: :class:`~numpy.ndarray` (N=3), optional A boolean mask which defines the magnetized volume in 3D. - projectors: list of :class:`~.Projector` - A list of all stored :class:`~.Projector` objects. - phase_maps: list of :class:`~.PhaseMap` - A list of all stored :class:`~.PhaseMap` objects. - phase_vec: :class:`~numpy.ndarray` (N=1) - The concatenaded, vectorized phase of all ;class:`~.PhaseMap` objects. Se_inv : :class:`~numpy.ndarray` (N=2), optional Inverted covariance matrix of the measurement errors. The matrix has size `NxN` with N being the length of the targetvector y (vectorized phase map information). - m: int - Size of the image space. - n: int - Size of the input space. + phase_maps: + A list of all stored :class:`~.PhaseMap` objects. + projectors: list of :class:`~.Projector` + A list of all stored :class:`~.Projector` objects. - ''' + """ - _log = logging.getLogger(__name__+'.DataSet') + _log = logging.getLogger(__name__ + '.DataSet') @property def a(self): + """The grid spacing in nm.""" return self._a @a.setter @@ -74,6 +64,7 @@ class DataSet(object): @property def mask(self): + """A boolean mask which defines the magnetized volume in 3D.""" return self._mask @mask.setter @@ -86,29 +77,35 @@ class DataSet(object): @property def m(self): + """Size of the image space.""" return np.sum([len(p.phase_vec) for p in self.phase_maps]) @property def n(self): + """Size of the input space.""" return 3 * np.sum(self.mask) @property def count(self): + """Number of phase maps and projectors in the dataset.""" return len(self.projectors) @property def phase_vec(self): + """The concatenaded, vectorized phase of all ;class:`~.PhaseMap` objects.""" return np.concatenate([p.phase_vec for p in self.phase_maps]) @property def hook_points(self): + """Hook points which determine the start of values of a phase map in the `phase_vec`.""" result = [0] for i, phase_map in enumerate(self.phase_maps): - result.append(result[i]+np.prod(phase_map.dim_uv)) + result.append(result[i] + np.prod(phase_map.dim_uv)) return result @property def phase_mappers(self): + """List of phase mappers, created on demand with the projectors in mind.""" dim_uv_set = set([p.dim_uv for p in self.projectors]) kernel_list = [Kernel(self.a, dim_uv) for dim_uv in dim_uv_set] return {kernel.dim_uv: PhaseMapperRDFC(kernel) for kernel in kernel_list} @@ -124,7 +121,7 @@ class DataSet(object): self.Se_inv = Se_inv self.phase_maps = [] self.projectors = [] - self._log.debug('Created: '+str(self)) + self._log.debug('Created: ' + str(self)) def __repr__(self): self._log.debug('Calling __repr__') @@ -136,7 +133,7 @@ class DataSet(object): return 'DataSet(a=%s, dim=%s, b_0=%s)' % (self.a, self.dim, self.b_0) def append(self, phase_map, projector): - '''Appends a data pair of phase map and projection infos to the data collection.` + """Appends a data pair of phase map and projection infos to the data collection.` Parameters ---------- @@ -149,9 +146,9 @@ class DataSet(object): ------- None - ''' + """ self._log.debug('Calling append') - assert isinstance(phase_map, PhaseMap) and isinstance(projector, Projector), \ + assert isinstance(phase_map, PhaseMap) and isinstance(projector, Projector), \ 'Argument has to be a tuple of a PhaseMap and a Projector object!' assert projector.dim == self.dim, '3D dimensions must match!' assert phase_map.dim_uv == projector.dim_uv, 'Projection dimensions (dim_uv) must match!' @@ -159,7 +156,7 @@ class DataSet(object): self.projectors.append(projector) def create_phase_maps(self, mag_data): - '''Create a list of phasemaps with the projectors in the dataset for a given + """Create a list of phasemaps with the projectors in the dataset for a given :class:`~.MagData` object. Parameters @@ -172,7 +169,7 @@ class DataSet(object): phase_maps : list of :class:`~.phasemap.PhaseMap` A list of the phase maps resulting from the projections specified in the dataset. - ''' + """ self._log.debug('Calling create_phase_maps') phase_maps = [] for projector in self.projectors: @@ -183,7 +180,7 @@ class DataSet(object): return phase_maps def set_Se_inv_block_diag(self, cov_list): - '''Set the Se_inv matrix as a block diagonal matrix + """Set the Se_inv matrix as a block diagonal matrix Parameters ---------- @@ -194,13 +191,13 @@ class DataSet(object): ------- None - ''' + """ self._log.debug('Calling set_Se_inv_block_diag') assert len(cov_list) == len(self.phase_maps), 'Needs one covariance matrix per phase map!' self.Se_inv = sparse.block_diag(cov_list).tocsr() def set_Se_inv_diag_with_conf(self, conf_list=None): - '''Set the Se_inv matrix as a block diagonal matrix from a list of confidence matrizes. + """Set the Se_inv matrix as a block diagonal matrix from a list of confidence matrizes. Parameters ---------- @@ -212,7 +209,7 @@ class DataSet(object): ------- None - ''' + """ self._log.debug('Calling set_Se_inv_diag_with_conf') if conf_list is None: # if no confidence matrizes are given, extract from the phase maps! conf_list = [phase_map.confidence for phase_map in self.phase_maps] @@ -220,7 +217,7 @@ class DataSet(object): self.set_Se_inv_block_diag(cov_list) def set_3d_mask(self, mask_list=None): - '''Set the 3D mask from a list of 2D masks. + """Set the 3D mask from a list of 2D masks. Parameters ---------- @@ -233,7 +230,7 @@ class DataSet(object): ------- None - ''' + """ self._log.debug('Calling set_3d_mask') if mask_list is None: # if no masks are given, extract from phase maps: mask_list = [phase_map.mask for phase_map in self.phase_maps] @@ -248,7 +245,7 @@ class DataSet(object): self.mask = np.where(mask_3d_inv == 0, True, False) def display_mask(self, ar_dens=1): - '''If it exists, display the 3D mask of the magnetization distribution. + """If it exists, display the 3D mask of the magnetization distribution. Parameters ---------- @@ -260,7 +257,7 @@ class DataSet(object): ------- None - ''' + """ self._log.debug('Calling display_mask') if self.mask is not None: from mayavi import mlab @@ -271,15 +268,15 @@ class DataSet(object): xx = xx[::ad, ::ad, ::ad].flatten() mask_vec = self.mask[::ad, ::ad, ::ad].flatten().astype(dtype=np.int) mlab.figure(size=(750, 700)) - plot = plot = mlab.points3d(xx, yy, zz, mask_vec, opacity=0.5, mode='cube', - scale_factor=ar_dens) + plot = mlab.points3d(xx, yy, zz, mask_vec, opacity=0.5, + mode='cube', scale_factor=ar_dens) mlab.outline(plot) mlab.axes(plot) return plot def display_phase(self, mag_data=None, title='Phase Map', cmap='RdBu', limit=None, norm=None): - '''Display all phasemaps saved in the :class:`~.DataSet` as a colormesh. + """Display all phasemaps saved in the :class:`~.DataSet` as a colormesh. Parameters ---------- @@ -303,7 +300,7 @@ class DataSet(object): ------- None - ''' + """ self._log.debug('Calling display_phase') if mag_data is not None: phase_maps = self.create_phase_maps(mag_data) @@ -311,12 +308,12 @@ class DataSet(object): phase_maps = self.phase_maps [phase_map.display_phase('{} ({})'.format(title, self.projectors[i].get_info()), cmap, limit, norm) - for (i, phase_map) in enumerate(phase_maps)] + for (i, phase_map) in enumerate(phase_maps)] plt.show() def display_combined(self, mag_data=None, title='Combined Plot', cmap='RdBu', limit=None, norm=None, gain='auto', interpolation='none', grad_encode='bright'): - '''Display all phasemaps and the resulting color coded holography images. + """Display all phasemaps and the resulting color coded holography images. Parameters ---------- @@ -350,7 +347,7 @@ class DataSet(object): ------- None - ''' + """ self._log.debug('Calling display_combined') if mag_data is not None: phase_maps = self.create_phase_maps(mag_data) diff --git a/pyramid/diagnostics.py b/pyramid/diagnostics.py index 7aa2b01..74274d0 100644 --- a/pyramid/diagnostics.py +++ b/pyramid/diagnostics.py @@ -5,24 +5,21 @@ """This module provides the :class:`~.Diagnostics` class for the calculation of diagnostics of a specified costfunction for a fixed magnetization distribution.""" +import logging -import numpy as np import matplotlib.pyplot as plt +import numpy as np import jutil from pyramid import fft from pyramid.magdata import MagData from pyramid.phasemap import PhaseMap -import logging - - __all__ = ['Diagnostics'] class Diagnostics(object): - - '''Class for calculating diagnostic properties of a specified costfunction. + """Class for calculating diagnostic properties of a specified costfunction. For the calculation of diagnostic properties, a costfunction and a magnetization distribution are specified at construction. With the :func:`~.set_position`, a position in 3D space can be @@ -48,20 +45,6 @@ class Diagnostics(object): Dimensions of the 3D magnetic distribution. row_idx: int Row index of the system matrix corresponding to the current position in 3D space. - cov_row: :class:`~numpy.ndarray` - Row of the covariance matrix (``S_a^-1+F'(x_f)^T S_e^-1 F'(x_f)``) which is needed for the - calculation of the gain and averaging kernel matrizes and which ideally contains the - variance at position `row_idx` for the current component and position in 3D. - std: float - Standard deviation of the chosen component at the current position (calculated when - needed). - gain_row: :class:`~numpy.ndarray` - Row of the gain matrix, which maps differences of phase measurements onto differences in - the retrieval result of the magnetization distribution(calculated when needed). - avrg_kern_row: :class:`~numpy.ndarray` - Row of the averaging kernel matrix (which is ideally the identity matrix), which describes - the smoothing introduced by the regularization (calculated when needed). - measure_contribution: :class:`~numpy.ndarray` Notes ----- @@ -70,26 +53,33 @@ class Diagnostics(object): avrg_kern_row --> gain_row --> std --> m_inv_row measure_contribution is independant - ''' + """ - _log = logging.getLogger(__name__+'.Diagnostics') + _log = logging.getLogger(__name__ + '.Diagnostics') @property def cov_row(self): + """Row of the covariance matrix (``S_a^-1+F'(x_f)^T S_e^-1 F'(x_f)``) which is needed for + the calculation of the gain and averaging kernel matrizes and which ideally contains the + variance at position `row_idx` for the current component and position in 3D.""" if not self._updated_cov_row: e_i = fft.zeros(self.cost.n, dtype=fft.FLOAT) e_i[self.row_idx] = 1 row = 2 * jutil.cg.conj_grad_solve(self._A, e_i, P=self._P, max_iter=self.max_iter) - self._std_row = row + self._std_row = np.asarray(row) self._updated_cov_row = True return self._std_row @property def std(self): + """Standard deviation of the chosen component at the current position (calculated when + needed).""" return np.sqrt(self.cov_row[self.row_idx]) @property def gain_row(self): + """Row of the gain matrix, which maps differences of phase measurements onto differences in + the retrieval result of the magnetization distribution(calculated when needed).""" if not self._updated_gain_row: self._gain_row = self.Se_inv.dot(self.fwd_model.jac_dot(self.x_rec, self.cov_row)) self._updated_gain_row = True @@ -97,6 +87,8 @@ class Diagnostics(object): @property def avrg_kern_row(self): + """Row of the averaging kernel matrix (which is ideally the identity matrix), which + describes the smoothing introduced by the regularization (calculated when needed).""" if not self._updated_avrg_kern_row: self._avrg_kern_row = self.fwd_model.jac_T_dot(self.x_rec, self.gain_row) self._updated_avrg_kern_row = True @@ -104,6 +96,9 @@ class Diagnostics(object): @property def measure_contribution(self): + """The sum over an averaging kernel matrix row, which is an indicator for wheter a point of + the solution is determined by the measurement (close to `1`) or by a priori information + (close to `0`).""" if not self._updated_measure_contribution: cache = self.fwd_model.jac_dot(self.x_rec, fft.ones(self.cost.n, fft.FLOAT)) cache = self.fwd_model.jac_T_dot(self.x_rec, self.Se_inv.dot(cache)) @@ -114,6 +109,8 @@ class Diagnostics(object): @property def pos(self): + """The current solution position, which specifies the 3D-point (and the component) of the + magnetization, for which diagnostics are calculated.""" return self._pos @pos.setter @@ -121,8 +118,8 @@ class Diagnostics(object): c, z, y, x = pos assert self.mask[z, y, x], 'Position is outside of the provided mask!' mask_vec = self.mask.flatten() - idx_3d = z*self.dim[1]*self.dim[2] + y*self.dim[2] + x - row_idx = c*np.prod(mask_vec.sum()) + mask_vec[:idx_3d].sum() + idx_3d = z * self.dim[1] * self.dim[2] + y * self.dim[2] + x + row_idx = c * np.prod(mask_vec.sum()) + mask_vec[:idx_3d].sum() if row_idx != self.row_idx: self._pos = pos self.row_idx = row_idx @@ -148,10 +145,10 @@ class Diagnostics(object): self._updated_measure_contribution = False self._A = jutil.operator.CostFunctionOperator(self.cost, self.x_rec) self._P = jutil.preconditioner.CostFunctionPreconditioner(self.cost, self.x_rec) - self._log.debug('Creating '+str(self)) + self._log.debug('Creating ' + str(self)) def get_avg_kern_row(self, pos=None): - '''Get the averaging kernel matrix row represented as a 3D magnetization distribution. + """Get the averaging kernel matrix row represented as a 3D magnetization distribution. Parameters ---------- @@ -163,16 +160,16 @@ class Diagnostics(object): mag_data_avg_kern: :class:`~pyramid.magdata.MagData` Averaging kernel matrix row represented as a 3D magnetization distribution - ''' + """ self._log.debug('Calling get_avg_kern_row') if pos is not None: self.pos = pos - mag_data_avg_kern = MagData(self.cost.data_set.a, fft.zeros((3,)+self.dim)) + mag_data_avg_kern = MagData(self.cost.data_set.a, fft.zeros((3,) + self.dim)) mag_data_avg_kern.set_vector(self.avrg_kern_row, mask=self.mask) return mag_data_avg_kern def calculate_averaging(self, pos=None): - '''Calculate and plot the averaging pixel number at a specified position for x, y or z. + """Calculate and plot the averaging pixel number at a specified position for x, y or z. Parameters ---------- @@ -189,9 +186,9 @@ class Diagnostics(object): Notes ----- - Uses the :func:`~.get_avg_kern_row' function + Uses the :func:`~.get_avg_kern_row` function - ''' + """ self._log.debug('Calling calculate_averaging') mag_data_avg_kern = self.get_avg_kern_row(pos) mag_x, mag_y, mag_z = mag_data_avg_kern.magnitude @@ -205,32 +202,36 @@ class Diagnostics(object): plt.plot(x, label='x', color='r', marker='o') plt.plot(y, label='y', color='g', marker='o') plt.plot(z, label='z', color='b', marker='o') - c = self.pos[0] + c = self.pos[0] # x, y or z component data = [x, y, z][c] col = ['r', 'g', 'b'][c] i_m = np.argmax(data) # Index of the maximum plt.axhline(y=data[i_m], ls='-', color=col) - plt.axhline(y=data[i_m]/2, ls='--', color=col) + plt.axhline(y=data[i_m] / 2, ls='--', color=col) # Left side: - for i in np.arange(i_m-1, -1, -1): - if data[i] < data[i_m]/2: - l = (data[i_m]/2-data[i])/(data[i+1]-data[i]) + i + l = i_m + for i in np.arange(i_m - 1, -1, -1): + if data[i] < data[i_m] / 2: + # Linear interpolation between i and i + 1 to find left fractional index position: + l = (data[i_m] / 2 - data[i]) / (data[i + 1] - data[i]) + i break # Right side: - for i in np.arange(i_m+1, data.size): - if data[i] < data[i_m]/2: - r = (data[i_m]/2-data[i-1])/(data[i]-data[i-1]) + i-1 + r = i_m + for i in np.arange(i_m + 1, data.size): + if data[i] < data[i_m] / 2: + # Linear interpolation between i and i - 1 to find right fractional index position: + r = (data[i_m] / 2 - data[i - 1]) / (data[i] - data[i - 1]) + i - 1 break # Calculate FWHM: fwhm = r - l px_avrg = 1 / fwhm - plt.vlines(x=[l, r], ymin=0, ymax=data[i_m]/2, linestyles=':', color=col) + plt.vlines(x=[l, r], ymin=0, ymax=data[i_m] / 2, linestyles=':', color=col) # Add legend: plt.legend() return px_avrg, (x, y, z) def get_gain_row_maps(self, pos=None): - '''Get the gain matrix row represented as a list of 2D (inverse) phase maps. + """Get the gain matrix row represented as a list of 2D (inverse) phase maps. Parameters ---------- @@ -248,13 +249,13 @@ class Diagnostics(object): in 3d per phase change at the position of the . Take this into account when plotting the maps (1/rad instead of rad). - ''' + """ self._log.debug('Calling get_gain_row_maps') if pos is not None: self.pos = pos hp = self.cost.data_set.hook_points gain_map_list = [] for i, projector in enumerate(self.cost.data_set.projectors): - gain = self.gain_row[hp[i]:hp[i+1]].reshape(projector.dim_uv) + gain = self.gain_row[hp[i]:hp[i + 1]].reshape(projector.dim_uv) gain_map_list.append(PhaseMap(self.cost.data_set.a, gain)) return gain_map_list diff --git a/pyramid/fft.py b/pyramid/fft.py index 88ea862..f81d867 100644 --- a/pyramid/fft.py +++ b/pyramid/fft.py @@ -11,33 +11,35 @@ FFT operations. """ +try: + import cPickle as pickle +except ImportError: + import pickle +import logging +import os import numpy as np -import cPickle as pickle -import os from pyramid.config import NTHREADS -import logging - - # pyFFTW depends on this -try: - from collections import Counter # analysis:ignore -except ImportError: - import collections_python27 - import collections - collections.Counter = collections_python27.Counter +# try: +# from collections import Counter +# except ImportError: +# from collections_python27 import Counter +# import collections +# +# collections.Counter = Counter try: import pyfftw + BACKEND = 'fftw' except ImportError: pyfftw = None BACKEND = 'numpy' print("pyFFTW module not found. Using numpy implementation.") - __all__ = ['PLANS', 'FLOAT', 'COMPLEX', 'dump_wisdom', 'load_wisdom', # analysis:ignore 'zeros', 'empty', 'configure_backend', 'fftn', 'ifftn', 'rfftn', 'irfftn', 'rfftn_adj', 'irfftn_adj'] @@ -45,8 +47,7 @@ _log = logging.getLogger(__name__) class FFTWCache(object): - - '''Class for adding FFTW Plans and on-demand lookups. + """Class for adding FFTW Plans and on-demand lookups. This class is instantiated in this module to store FFTW plans and for the lookup of the former. @@ -59,33 +60,71 @@ class FFTWCache(object): ----- This class is used internally and is not normally not intended to be used directly by the user. - ''' + """ - _log = logging.getLogger(__name__+'.FFTWCache') + _log = logging.getLogger(__name__ + '.FFTWCache') def __init__(self): self._log.debug('Calling __init__') self.cache = dict() - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) def add_fftw(self, fft_type, fftw_obj, s, axes, nthreads): + """Add an FFTW object to the cache. + + Parameters + ---------- + fft_type: basestring + Identifier sting for the FFT type ('fftn', 'ifftn', 'rfftn', 'irfftn'). + fftw_obj: :class:`~pyfftw.FFTW` object + The FFTW object which should be added to the cache. + s: tuple of ints + Shape of the output array. + axes: tuple of ints + The axes along which the FFTW should be executed. + nthreads: int + Number of threads which should be used. + + """ self._log.debug('Calling add_fftw') in_arr = fftw_obj.get_input_array() - key = (fft_type, in_arr.shape, in_arr.dtype, nthreads) + key = (fft_type, in_arr.shape, in_arr.dtype, s, axes, nthreads) self.cache[key] = fftw_obj def lookup_fftw(self, fft_type, in_arr, s, axes, nthreads): + """ + + Parameters + ---------- + fft_type: basestring + Identifier sting for the FFT type ('fftn', 'ifftn', 'rfftn', 'irfftn'). + in_arr: + Input array, internally, just the `dtype` and the `shape` are used to identify the FFT. + s: tuple of ints + Shape of the output array. + axes: tuple of ints + The axes along which the FFTW should be executed. + nthreads: int + Number of threads which should be used. + + Returns + ------- + fftw_obj: :class:`~pyfftw.FFTW` object + The requested FFTW object. + + """ self._log.debug('Calling lookup_fftw') - key = (fft_type, in_arr.shape, in_arr.dtype, nthreads) + key = (fft_type, in_arr.shape, in_arr.dtype, s, axes, nthreads) return self.cache.get(key, None) def clear_cache(self): + """Clear the cache.""" self._log.debug('Calling clear_cache') self.cache = dict() PLANS = FFTWCache() -FLOAT = np.float32 # One convenient place to +FLOAT = np.float32 # One convenient place to COMPLEX = np.complex64 # change from 32 to 64 bit @@ -119,9 +158,9 @@ def _irfftn_adj_numpy(a): n = a.shape[-1] // 2 + 1 out_arr = _fftn_numpy(a, axes=(-1,)) / a.shape[-1] if a.shape[-1] % 2 == 0: # even - out_arr[:, 1:n - 1] += np.conj(out_arr[:, :n-1:-1]) + out_arr[:, 1:n - 1] += np.conj(out_arr[:, :n - 1:-1]) else: # odd - out_arr[:, 1:n] += np.conj(out_arr[:, :n-1:-1]) + out_arr[:, 1:n] += np.conj(out_arr[:, :n - 1:-1]) axes = tuple(range(len(out_arr.shape[:-1]))) return _fftn_numpy(out_arr[:, :n], axes=axes) / np.prod(out_arr.shape[:-1]) @@ -169,7 +208,7 @@ def _irfftn_fftw(a, s=None, axes=None): def _rfftn_adj_fftw(a): - # Careful just works for even a (which is guaranteed by the kernel!) + # Careful: just works for even a (which is guaranteed by the kernel!) n = 2 * (a.shape[-1] - 1) out_shape = a.shape[:-1] + (n,) out_arr = zeros(out_shape, dtype=a.dtype) @@ -181,9 +220,9 @@ def _irfftn_adj_fftw(a): out_arr = _fftn_fftw(a, axes=(-1,)) / a.shape[-1] # FFT of last axis n = a.shape[-1] // 2 + 1 if a.shape[-1] % 2 == 0: # even - out_arr[:, 1:n-1] += np.conj(out_arr[:, :n-1:-1]) + out_arr[:, 1:n - 1] += np.conj(out_arr[:, :n - 1:-1]) else: # odd - out_arr[:, 1:n] += np.conj(out_arr[:, :n-1:-1]) + out_arr[:, 1:n] += np.conj(out_arr[:, :n - 1:-1]) axes = tuple(range(len(out_arr.shape[:-1]))) return _fftn_fftw(out_arr[:, :n], axes=axes) / np.prod(out_arr.shape[:-1]) @@ -191,7 +230,7 @@ def _irfftn_adj_fftw(a): # These wisdom functions do nothing if pyFFTW is not available: def dump_wisdom(fname): - '''Wrapper function for the pyfftw.export_wisdom(), which uses a pickle dump. + """Wrapper function for the pyfftw.export_wisdom(), which uses a pickle dump. Parameters ---------- @@ -202,7 +241,7 @@ def dump_wisdom(fname): ------- None - ''' + """ _log.debug('Calling dump_wisdom') if pyfftw is not None: with open(fname, 'wb') as fp: @@ -210,7 +249,7 @@ def dump_wisdom(fname): def load_wisdom(fname): - '''Wrapper function for the pyfftw.import_wisdom(), which uses a pickle to load a file. + """Wrapper function for the pyfftw.import_wisdom(), which uses a pickle to load a file. Parameters ---------- @@ -221,7 +260,7 @@ def load_wisdom(fname): ------- None - ''' + """ _log.debug('Calling load_wisdom') if pyfftw is not None: if not os.path.exists(fname): @@ -233,7 +272,7 @@ def load_wisdom(fname): # Array setups: def empty(shape, dtype=FLOAT): - '''Return a new array of given shape and type without initializing entries. + """Return a new array of given shape and type without initializing entries. Parameters ---------- @@ -247,7 +286,7 @@ def empty(shape, dtype=FLOAT): out: :class:`~numpy.ndarray` The created array. - ''' + """ _log.debug('Calling empty') result = np.empty(shape, dtype) if pyfftw is not None: @@ -256,7 +295,7 @@ def empty(shape, dtype=FLOAT): def zeros(shape, dtype=FLOAT): - '''Return a new array of given shape and type, filled with zeros. + """Return a new array of given shape and type, filled with zeros. Parameters ---------- @@ -270,7 +309,7 @@ def zeros(shape, dtype=FLOAT): out: :class:`~numpy.ndarray` The created array. - ''' + """ _log.debug('Calling zeros') result = np.zeros(shape, dtype) if pyfftw is not None: @@ -279,7 +318,7 @@ def zeros(shape, dtype=FLOAT): def ones(shape, dtype=FLOAT): - '''Return a new array of given shape and type, filled with ones. + """Return a new array of given shape and type, filled with ones. Parameters ---------- @@ -293,7 +332,7 @@ def ones(shape, dtype=FLOAT): out: :class:`~numpy.ndarray` The created array. - ''' + """ _log.debug('Calling ones') result = np.ones(shape, dtype) if pyfftw is not None: @@ -303,7 +342,7 @@ def ones(shape, dtype=FLOAT): # Configure backend: def configure_backend(backend): - '''Change FFT backend. + """Change FFT backend. Parameters ---------- @@ -314,7 +353,7 @@ def configure_backend(backend): ------- None - ''' + """ _log.debug('Calling configure_backend') global fftn global ifftn @@ -323,7 +362,7 @@ def configure_backend(backend): global rfftn_adj global irfftn_adj global BACKEND - if backend == "numpy": + if backend == 'numpy': fftn = _fftn_numpy ifftn = _ifftn_numpy rfftn = _rfftn_numpy @@ -331,7 +370,7 @@ def configure_backend(backend): rfftn_adj = _rfftn_adj_numpy irfftn_adj = _irfftn_adj_numpy BACKEND = 'numpy' - elif backend == "fftw": + elif backend == 'fftw': if pyfftw is not None: fftn = _fftn_fftw ifftn = _ifftn_fftw @@ -341,11 +380,11 @@ def configure_backend(backend): irfftn_adj = _irfftn_adj_fftw BACKEND = 'pyfftw' else: - print("Error: FFTW requested but not available") + print('Error: FFTW requested but not available') # On import: if pyfftw is not None: - configure_backend("fftw") + configure_backend('fftw') else: - configure_backend("numpy") + configure_backend('numpy') diff --git a/pyramid/forwardmodel.py b/pyramid/forwardmodel.py index 765979b..f3e97fe 100644 --- a/pyramid/forwardmodel.py +++ b/pyramid/forwardmodel.py @@ -5,26 +5,23 @@ """This module provides the :class:`~.ForwardModel` class which represents a strategy to map a threedimensional magnetization distribution onto a two-dimensional phase map.""" +from __future__ import division, print_function -from __future__ import division - +import logging +import multiprocessing as mp import sys + import numpy as np -import multiprocessing as mp +from pyramid.dataset import DataSet from pyramid.magdata import MagData from pyramid.ramp import Ramp -from pyramid.dataset import DataSet - -import logging - __all__ = ['ForwardModel', 'DistributedForwardModel'] class ForwardModel(object): - - '''Class for mapping 3D magnetic distributions to 2D phase maps. + """Class for mapping 3D magnetic distributions to 2D phase maps. Represents a strategy for the mapping of a 3D magnetic distribution to two-dimensional phase maps. A :class:`~.DataSet` object is given which is used as input for the model @@ -46,9 +43,9 @@ class ForwardModel(object): n: int Size of the input space. Number of voxels of the 3-dimensional grid. - ''' + """ - _log = logging.getLogger(__name__+'.ForwardModel') + _log = logging.getLogger(__name__ + '.ForwardModel') def __init__(self, data_set, ramp_order=None): self._log.debug('Calling __init__') @@ -62,8 +59,8 @@ class ForwardModel(object): self.n += self.ramp.n self.shape = (self.m, self.n) self.hook_points = data_set.hook_points - self.mag_data = MagData(self.data_set.a, np.zeros((3,)+self.data_set.dim)) - self._log.debug('Creating '+str(self)) + self.mag_data = MagData(self.data_set.a, np.zeros((3,) + self.data_set.dim)) + self._log.debug('Creating ' + str(self)) def __repr__(self): self._log.debug('Calling __repr__') @@ -71,7 +68,7 @@ class ForwardModel(object): def __str__(self): self._log.debug('Calling __str__') - return 'ForwardModel(data_set=%s)' % (self.data_set) + return 'ForwardModel(data_set=%s)' % self.data_set def __call__(self, x): # Extract ramp parameters if necessary (x will be shortened!): @@ -86,11 +83,11 @@ class ForwardModel(object): mapper = self.phase_mappers[projector.dim_uv] phase_map = mapper(projector(self.mag_data)) phase_map += self.ramp(i) # add ramp! - result[hp[i]:hp[i+1]] = phase_map.phase_vec + result[hp[i]:hp[i + 1]] = phase_map.phase_vec return np.reshape(result, -1) def jac_dot(self, x, vector): - '''Calculate the product of the Jacobi matrix with a given `vector`. + """Calculate the product of the Jacobi matrix with a given `vector`. Parameters ---------- @@ -109,7 +106,7 @@ class ForwardModel(object): Product of the Jacobi matrix (which is not explicitely calculated) with the input `vector`. - ''' + """ # Extract ramp parameters if necessary (vector will be shortened!): vector = self.ramp.extract_ramp_params(vector) # Reset mag_data and fill with vector: @@ -123,11 +120,11 @@ class ForwardModel(object): mapper = self.phase_mappers[projector.dim_uv] res = mapper.jac_dot(projector.jac_dot(mag_vec)) res += self.ramp.jac_dot(i) # add ramp! - result[hp[i]:hp[i+1]] = res + result[hp[i]:hp[i + 1]] = res return result def jac_T_dot(self, x, vector): - ''''Calculate the product of the transposed Jacobi matrix with a given `vector`. + """'Calculate the product of the transposed Jacobi matrix with a given `vector`. Parameters ---------- @@ -144,11 +141,11 @@ class ForwardModel(object): Product of the transposed Jacobi matrix (which is not explicitely calculated) with the input `vector`. If necessary, transposed ramp parameters are concatenated. - ''' - proj_T_result = np.zeros(3*np.prod(self.data_set.dim)) + """ + proj_T_result = np.zeros(3 * np.prod(self.data_set.dim)) hp = self.hook_points for i, projector in enumerate(self.data_set.projectors): - sub_vec = vector[hp[i]:hp[i+1]] + sub_vec = vector[hp[i]:hp[i + 1]] mapper = self.phase_mappers[projector.dim_uv] proj_T_result += projector.jac_T_dot(mapper.jac_T_dot(sub_vec)) self.mag_data.mag_vec = proj_T_result @@ -157,23 +154,18 @@ class ForwardModel(object): return np.concatenate((result, ramp_params)) def finalize(self): - ''''Finalize the processes and let them join the master process (NOT USED HERE!). - - Parameters - ---------- - None + """'Finalize the processes and let them join the master process (NOT USED HERE!). Returns ------- None - ''' + """ pass class DistributedForwardModel(ForwardModel): - - '''Multiprocessing class for mapping 3D magnetic distributions to 2D phase maps. + """Multiprocessing class for mapping 3D magnetic distributions to 2D phase maps. Subclass of the :class:`~.ForwardModel` class which implements multiprocessing strategies to speed up the calculations. The interface is the same, internally, the processes and one @@ -189,14 +181,10 @@ class DistributedForwardModel(ForwardModel): Polynomial order of the additional phase ramp which will be added to the phase maps. All ramp parameters have to be at the end of the input vector and are split automatically. Default is None (no ramps are added). - m: int - Size of the image space. Number of pixels of the 2-dimensional projected grid. - n: int - Size of the input space. Number of voxels of the 3-dimensional grid. nprocs: int Number of processes which should be created. Default is 1 (not recommended). - ''' + """ def __init__(self, data_set, ramp_order=None, nprocs=1): # Evoke super constructor to set up the normal ForwardModel: @@ -213,8 +201,8 @@ class DistributedForwardModel(ForwardModel): sub_data = DataSet(self.data_set.a, self.data_set.dim, self.data_set.b_0, self.data_set.mask, self.data_set.Se_inv) # Distribute data to SubDataSets: - start = proc_id*img_per_proc - stop = np.min(((proc_id+1)*img_per_proc, self.data_set.count)) + start = proc_id * img_per_proc + stop = np.min(((proc_id + 1) * img_per_proc, self.data_set.count)) self.proc_hook_points.append(hp[stop]) sub_data.phase_maps = self.data_set.phase_maps[start:stop] sub_data.projectors = self.data_set.projectors[start:stop] @@ -228,7 +216,7 @@ class DistributedForwardModel(ForwardModel): self.processes.append(p) # Start process: p.start() - self._log.debug('Creating '+str(self)) + self._log.debug('Creating ' + str(self)) def __call__(self, x): # Extract ramp parameters if necessary (x will be shortened!): @@ -243,15 +231,15 @@ class DistributedForwardModel(ForwardModel): # Calculate ramps (if necessary): if self.ramp_order is not None: for i in range(self.data_set.count): - result[hp[i]:hp[i+1]] += self.ramp(i).phase.ravel() + result[hp[i]:hp[i + 1]] += self.ramp(i).phase.ravel() # Get process results from the pipes: for proc_id in range(self.nprocs): - result[php[proc_id]:php[proc_id+1]] += self.pipes[proc_id][0].recv() + result[php[proc_id]:php[proc_id + 1]] += self.pipes[proc_id][0].recv() # Return result: return result def jac_dot(self, x, vector): - '''Calculate the product of the Jacobi matrix with a given `vector`. + """Calculate the product of the Jacobi matrix with a given `vector`. Parameters ---------- @@ -270,7 +258,7 @@ class DistributedForwardModel(ForwardModel): Product of the Jacobi matrix (which is not explicitely calculated) with the input `vector`. - ''' + """ # Extract ramp parameters if necessary (x will be shortened!): vector = self.ramp.extract_ramp_params(vector) # Distribute input to processes and start working: @@ -283,15 +271,15 @@ class DistributedForwardModel(ForwardModel): # Calculate ramps (if necessary): if self.ramp_order is not None: for i in range(self.data_set.count): - result[hp[i]:hp[i+1]] += self.ramp.jac_dot(i) + result[hp[i]:hp[i + 1]] += self.ramp.jac_dot(i) # Get process results from the pipes: for proc_id in range(self.nprocs): - result[php[proc_id]:php[proc_id+1]] += self.pipes[proc_id][0].recv() + result[php[proc_id]:php[proc_id + 1]] += self.pipes[proc_id][0].recv() # Return result: return result def jac_T_dot(self, x, vector): - ''''Calculate the product of the transposed Jacobi matrix with a given `vector`. + """'Calculate the product of the transposed Jacobi matrix with a given `vector`. Parameters ---------- @@ -308,35 +296,30 @@ class DistributedForwardModel(ForwardModel): Product of the transposed Jacobi matrix (which is not explicitely calculated) with the input `vector`. If necessary, transposed ramp parameters are concatenated. - ''' + """ php = self.proc_hook_points # Distribute input to processes and start working: for proc_id in range(self.nprocs): - sub_vec = vector[php[proc_id]:php[proc_id+1]] + sub_vec = vector[php[proc_id]:php[proc_id + 1]] self.pipes[proc_id][0].send(('jac_T_dot', (None, sub_vec))) # Calculate ramps: ramp_params = self.ramp.jac_T_dot(vector) # calculate ramp_params separately! # Initialize result vector: - result = np.zeros(3*self.data_set.mask.sum()) + result = np.zeros(3 * self.data_set.mask.sum()) # Get process results from the pipes: for proc_id in range(self.nprocs): - sub_vec = vector[php[proc_id]:php[proc_id+1]] result += self.pipes[proc_id][0].recv() # Return result: return np.concatenate((result, ramp_params)) def finalize(self): - ''''Finalize the processes and let them join the master process. - - Parameters - ---------- - None + """'Finalize the processes and let them join the master process. Returns ------- None - ''' + """ # Finalize processes: for proc_id in range(self.nprocs): self.pipes[proc_id][0].send('STOP') @@ -347,12 +330,12 @@ class DistributedForwardModel(ForwardModel): def _worker(fwd_model, pipe): # Has to be directly accessible in the module as a function, NOT a method of a class instance! - print '... {} starting!'.format(mp.current_process().name) + print('... {} starting!'.format(mp.current_process().name)) sys.stdout.flush() for method, arguments in iter(pipe.recv, 'STOP'): # '... {} processes method {}'.format(mp.current_process().name, method) sys.stdout.flush() result = getattr(fwd_model, method)(*arguments) pipe.send(result) - print '... ', mp.current_process().name, 'exiting!' + print('... ', mp.current_process().name, 'exiting!') sys.stdout.flush() diff --git a/pyramid/kernel.py b/pyramid/kernel.py index 317ce38..21b7d9a 100644 --- a/pyramid/kernel.py +++ b/pyramid/kernel.py @@ -5,22 +5,21 @@ """This module provides the :class:`~.Kernel` class, representing the phase contribution of one single magnetized pixel.""" +from __future__ import print_function + +import logging import numpy as np from pyramid import fft -import logging - - __all__ = ['Kernel', 'PHI_0'] PHI_0 = 2067.83 # magnetic flux in T*nm² class Kernel(object): - - '''Class for calculating kernel matrices for the phase calculation. + """Class for calculating kernel matrices for the phase calculation. Represents the phase of a single magnetized pixel for two orthogonal directions (`u` and `v`), which can be accessed via the corresponding attributes. The default elementary geometry is @@ -64,36 +63,36 @@ class Kernel(object): slice_mag : tuple (N=2) of :class:`slice` A tuple of :class:`slice` objects to extract the original FOV from the increased one with size `dim_pad` for the projected magnetization distribution. - pwr_vec: tuple of 2 int, optional + prw_vec: tuple of 2 int, optional A two-component vector describing the displacement of the reference wave to include perturbation of this reference by the object itself (via fringing fields). - ''' + """ - _log = logging.getLogger(__name__+'.Kernel') + _log = logging.getLogger(__name__ + '.Kernel') def __init__(self, a, dim_uv, b_0=1., prw_vec=None, geometry='disc'): self._log.debug('Calling __init__') # Set basic properties: self.dim_uv = dim_uv # Dimensions of the FOV - self.dim_kern = tuple(2*np.array(dim_uv)-1) # Dimensions of the kernel + self.dim_kern = tuple(2 * np.array(dim_uv) - 1) # Dimensions of the kernel self.a = a self.geometry = geometry # Set up FFT: if fft.BACKEND == 'pyfftw': - self.dim_pad = tuple(2*np.array(dim_uv)) # is at least even (not nec. power of 2) + self.dim_pad = tuple(2 * np.array(dim_uv)) # is at least even (not nec. power of 2) elif fft.BACKEND == 'numpy': - self.dim_pad = tuple(2**np.ceil(np.log2(2*np.array(dim_uv))).astype(int)) # pow(2) - self.dim_fft = (self.dim_pad[0], self.dim_pad[1]//2+1) # last axis is real - self.slice_phase = (slice(dim_uv[0]-1, self.dim_kern[0]), # Shift because kernel center - slice(dim_uv[1]-1, self.dim_kern[1])) # is not at (0, 0)! + self.dim_pad = tuple(2 ** np.ceil(np.log2(2 * np.array(dim_uv))).astype(int)) # pow(2) + self.dim_fft = (self.dim_pad[0], self.dim_pad[1] // 2 + 1) # last axis is real + self.slice_phase = (slice(dim_uv[0] - 1, self.dim_kern[0]), # Shift because kernel center + slice(dim_uv[1] - 1, self.dim_kern[1])) # is not at (0, 0)! self.slice_mag = (slice(0, dim_uv[0]), # Magnetization is padded on the far end! slice(0, dim_uv[1])) # (Phase cutout is shifted as listed above) # Calculate kernel (single pixel phase): - coeff = b_0 * a**2 / (2*PHI_0) # Minus is gone because of negative z-direction + coeff = b_0 * a ** 2 / (2 * PHI_0) # Minus is gone because of negative z-direction v_dim, u_dim = dim_uv - u = np.linspace(-(u_dim-1), u_dim-1, num=2*u_dim-1) - v = np.linspace(-(v_dim-1), v_dim-1, num=2*v_dim-1) + u = np.linspace(-(u_dim - 1), u_dim - 1, num=2 * u_dim - 1) + v = np.linspace(-(v_dim - 1), v_dim - 1, num=2 * v_dim - 1) uu, vv = np.meshgrid(u, v) self.u = fft.empty(self.dim_kern, fft.FLOAT) self.v = fft.empty(self.dim_kern, fft.FLOAT) @@ -108,49 +107,46 @@ class Kernel(object): # Calculate Fourier trafo of kernel components: self.u_fft = fft.rfftn(self.u, self.dim_pad) self.v_fft = fft.rfftn(self.v, self.dim_pad) - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) def __repr__(self): self._log.debug('Calling __repr__') return '%s(a=%r, dim_uv=%r, geometry=%r)' % \ - (self.__class__, self.a, self.dim_uv, self.geometry) + (self.__class__, self.a, self.dim_uv, self.geometry) def __str__(self): self._log.debug('Calling __str__') return 'Kernel(a=%s, dim_uv=%s, geometry=%s)' % \ - (self.a, self.dim_uv, self.geometry) + (self.a, self.dim_uv, self.geometry) def _get_elementary_phase(self, geometry, n, m, a): self._log.debug('Calling _get_elementary_phase') if geometry == 'disc': in_or_out = ~ np.logical_and(n == 0, m == 0) - return m / (n**2 + m**2 + 1E-30) * in_or_out + return m / (n ** 2 + m ** 2 + 1E-30) * in_or_out elif geometry == 'slab': - def F_a(n, m): - A = np.log(a**2 * (n**2 + m**2)) + def _F_a(n, m): + A = np.log(a ** 2 * (n ** 2 + m ** 2)) B = np.arctan(n / m) - return n*A - 2*n + 2*m*B - return 0.5 * (F_a(n-0.5, m-0.5) - F_a(n+0.5, m-0.5) - - F_a(n-0.5, m+0.5) + F_a(n+0.5, m+0.5)) + return n * A - 2 * n + 2 * m * B - def print_info(self): - '''Print information about the kernel. + return 0.5 * (_F_a(n - 0.5, m - 0.5) - _F_a(n + 0.5, m - 0.5) + - _F_a(n - 0.5, m + 0.5) + _F_a(n + 0.5, m + 0.5)) - Parameters - ---------- - None + def print_info(self): + """Print information about the kernel. Returns ------- None - ''' + """ self._log.debug('Calling print_info') - print 'Shape of the FOV :', self.dim_uv - print 'Shape of the Kernel:', self.dim_kern - print 'Zero-padded shape :', self.dim_pad - print 'Shape of the FFT :', self.dim_fft - print 'Slice for the phase:', self.slice_phase - print 'Slice for the magn.:', self.slice_mag - print 'Grid spacing: {} nm'.format(self.a) - print 'Geometry:', self.geometry + print('Shape of the FOV :', self.dim_uv) + print('Shape of the Kernel:', self.dim_kern) + print('Zero-padded shape :', self.dim_pad) + print('Shape of the FFT :', self.dim_fft) + print('Slice for the phase:', self.slice_phase) + print('Slice for the magn.:', self.slice_mag) + print('Grid spacing: {} nm'.format(self.a)) + print('Geometry:', self.geometry) diff --git a/pyramid/magcreator.py b/pyramid/magcreator.py index e42d097..a228a13 100644 --- a/pyramid/magcreator.py +++ b/pyramid/magcreator.py @@ -16,37 +16,34 @@ center. """ - from __future__ import division -import numpy as np -from numpy import pi import abc - import logging +import numpy as np +from numpy import pi __all__ = ['Shapes', 'create_mag_dist_homog', 'create_mag_dist_vortex'] _log = logging.getLogger(__name__) class Shapes(object): - - '''Abstract class containing functions for generating magnetic shapes. + """Abstract class containing functions for generating magnetic shapes. The :class:`~.Shapes` class is a collection of some methods that return a 3-dimensional matrix that represents the magnetized volume and consists of values between 0 and 1. This matrix is used in the functions of the :mod:`~.magcreator` module to create :class:`~pyramid.magdata.MagData` objects which store the magnetic informations. - ''' + """ __metaclass__ = abc.ABCMeta - _log = logging.getLogger(__name__+'.Shapes') + _log = logging.getLogger(__name__ + '.Shapes') @classmethod def slab(cls, dim, center, width): - '''Create the shape of a slab. + """Create the shape of a slab. Parameters ---------- @@ -62,20 +59,20 @@ class Shapes(object): mag_shape : :class:`~numpy.ndarray` (N=3) The magnetic shape as a 3D-array with values between 1 and 0. - ''' + """ cls._log.debug('Calling slab') assert np.shape(dim) == (3,), 'Parameter dim has to be a tuple of length 3!' assert np.shape(center) == (3,), 'Parameter center has to be a tuple of length 3!' assert np.shape(width) == (3,), 'Parameter width has to be a tuple of length 3!' zz, yy, xx = np.indices(dim) + 0.5 - xx_shape = np.where(abs(xx-center[2]) <= width[2]/2, True, False) - yy_shape = np.where(abs(yy-center[1]) <= width[1]/2, True, False) - zz_shape = np.where(abs(zz-center[0]) <= width[0]/2, True, False) - return np.logical_and.reduce((xx_shape, yy_shape, zz_shape)) + xx_shape = np.where(abs(xx - center[2]) <= width[2] / 2, True, False) + yy_shape = np.where(abs(yy - center[1]) <= width[1] / 2, True, False) + zz_shape = np.where(abs(zz - center[0]) <= width[0] / 2, True, False) + return np.logical_and(np.logical_and(xx_shape, yy_shape), zz_shape) @classmethod def disc(cls, dim, center, radius, height, axis='z'): - '''Create the shape of a cylindrical disc in x-, y-, or z-direction. + """Create the shape of a cylindrical disc in x-, y-, or z-direction. Parameters ---------- @@ -95,7 +92,7 @@ class Shapes(object): mag_shape : :class:`~numpy.ndarray` (N=3) The magnetic shape as a 3D-array with values between 1 and 0. - ''' + """ cls._log.debug('Calling disc') assert np.shape(dim) == (3,), 'Parameter dim has to be a a tuple of length 3!' assert np.shape(center) == (3,), 'Parameter center has to be a a tuple of length 3!' @@ -112,12 +109,14 @@ class Shapes(object): uu, vv, ww = zz, xx, yy elif axis == 'x': uu, vv, ww = yy, zz, xx + else: + raise ValueError('{} is not a valid argument (use x, y or z)'.format(axis)) return np.logical_and(np.where(np.hypot(uu, vv) <= radius, True, False), - np.where(abs(ww) <= height/2, True, False)) + np.where(abs(ww) <= height / 2, True, False)) @classmethod def ellipse(cls, dim, center, width, height, axis='z'): - '''Create the shape of an elliptical cylinder in x-, y-, or z-direction. + """Create the shape of an elliptical cylinder in x-, y-, or z-direction. Parameters ---------- @@ -137,7 +136,7 @@ class Shapes(object): mag_shape : :class:`~numpy.ndarray` (N=3) The magnetic shape as a 3D-array with values between 1 and 0. - ''' + """ cls._log.debug('Calling ellipse') assert np.shape(dim) == (3,), 'Parameter dim has to be a a tuple of length 3!' assert np.shape(center) == (3,), 'Parameter center has to be a a tuple of length 3!' @@ -154,13 +153,15 @@ class Shapes(object): uu, vv, ww = xx, zz, yy elif axis == 'x': uu, vv, ww = yy, zz, xx - distance = np.hypot(uu/(width[1]/2), vv/(width[0]/2)) + else: + raise ValueError('{} is not a valid argument (use x, y or z)'.format(axis)) + distance = np.hypot(uu / (width[1] / 2), vv / (width[0] / 2)) return np.logical_and(np.where(distance <= 1, True, False), - np.where(abs(ww) <= height/2, True, False)) + np.where(abs(ww) <= height / 2, True, False)) @classmethod def sphere(cls, dim, center, radius): - '''Create the shape of a sphere. + """Create the shape of a sphere. Parameters ---------- @@ -176,18 +177,18 @@ class Shapes(object): mag_shape : :class:`~numpy.ndarray` (N=3) The magnetic shape as a 3D-array with values between 1 and 0. - ''' + """ cls._log.debug('Calling sphere') assert np.shape(dim) == (3,), 'Parameter dim has to be a a tuple of length 3!' assert np.shape(center) == (3,), 'Parameter center has to be a a tuple of length 3!' assert radius > 0 and np.shape(radius) == (), 'Radius has to be a positive scalar value!' zz, yy, xx = np.indices(dim) + 0.5 - distance = np.sqrt((xx-center[2])**2 + (yy-center[1])**2 + (zz-center[0])**2) + distance = np.sqrt((xx - center[2]) ** 2 + (yy - center[1]) ** 2 + (zz - center[0]) ** 2) return np.where(distance <= radius, True, False) @classmethod def ellipsoid(cls, dim, center, width): - '''Create the shape of an ellipsoid. + """Create the shape of an ellipsoid. Parameters ---------- @@ -203,20 +204,20 @@ class Shapes(object): mag_shape : :class:`~numpy.ndarray` (N=3) The magnetic shape as a 3D-array with values between 1 and 0. - ''' + """ cls._log.debug('Calling ellipsoid') assert np.shape(dim) == (3,), 'Parameter dim has to be a a tuple of length 3!' assert np.shape(center) == (3,), 'Parameter center has to be a a tuple of length 3!' assert np.shape(width) == (3,), 'Parameter width has to be a a tuple of length 3!' zz, yy, xx = np.indices(dim) + 0.5 - distance = np.sqrt(((xx-center[2]) / (width[2]/2))**2 - + ((yy-center[1]) / (width[1]/2))**2 - + ((zz-center[0]) / (width[0]/2))**2) + distance = np.sqrt(((xx - center[2]) / (width[2] / 2)) ** 2 + + ((yy - center[1]) / (width[1] / 2)) ** 2 + + ((zz - center[0]) / (width[0] / 2)) ** 2) return np.where(distance <= 1, True, False) @classmethod def filament(cls, dim, pos, axis='y'): - '''Create the shape of a filament. + """Create the shape of a filament. Parameters ---------- @@ -234,7 +235,7 @@ class Shapes(object): mag_shape : :class:`~numpy.ndarray` (N=3) The magnetic shape as a 3D-array with values between 1 and 0. - ''' + """ cls._log.debug('Calling filament') assert np.shape(dim) == (3,), 'Parameter dim has to be a tuple of length 3!' assert np.shape(pos) == (2,), 'Parameter pos has to be a tuple of length 2!' @@ -250,7 +251,7 @@ class Shapes(object): @classmethod def pixel(cls, dim, pixel): - '''Create the shape of a single pixel. + """Create the shape of a single pixel. Parameters ---------- @@ -264,7 +265,7 @@ class Shapes(object): mag_shape : :class:`~numpy.ndarray` (N=3) The magnetic shape as a 3D-array with values between 1 and 0. - ''' + """ cls._log.debug('Calling pixel') assert np.shape(dim) == (3,), 'Parameter dim has to be a tuple of length 3!' assert np.shape(pixel) == (3,), 'Parameter pixel has to be a tuple of length 3!' @@ -273,8 +274,8 @@ class Shapes(object): return mag_shape -def create_mag_dist_homog(mag_shape, phi, theta=pi/2, magnitude=1): - '''Create a 3-dimensional magnetic distribution of a homogeneously magnetized object. +def create_mag_dist_homog(mag_shape, phi, theta=pi / 2, magnitude=1): + """Create a 3-dimensional magnetic distribution of a homogeneously magnetized object. Parameters ---------- @@ -294,7 +295,7 @@ def create_mag_dist_homog(mag_shape, phi, theta=pi/2, magnitude=1): The magnetic distribution as a tuple of the 3 components in `x`-, `y`- and `z`-direction on the 3-dimensional grid. - ''' + """ _log.debug('Calling create_mag_dist_homog') dim = np.shape(mag_shape) assert len(dim) == 3, 'Magnetic shapes must describe 3-dimensional distributions!' @@ -305,7 +306,7 @@ def create_mag_dist_homog(mag_shape, phi, theta=pi/2, magnitude=1): def create_mag_dist_vortex(mag_shape, center=None, axis='z', magnitude=1): - '''Create a 3-dimensional magnetic distribution of a homogeneous magnetized object. + """Create a 3-dimensional magnetic distribution of a homogeneous magnetized object. Parameters ---------- @@ -333,22 +334,22 @@ def create_mag_dist_vortex(mag_shape, center=None, axis='z', magnitude=1): reside at coordinates with _.5 at the end), i.e. integer values should be used as center coordinates (e.g. coordinate 1 lies between the first and the second pixel). - ''' + """ _log.debug('Calling create_mag_dist_vortex') - dim = np.shape(mag_shape) + dim = mag_shape.shape assert len(dim) == 3, 'Magnetic shapes must describe 3-dimensional distributions!' assert axis in {'z', 'y', 'x'}, 'Axis has to be x, y or z (as a string)!' assert center is None or len(center) in {2, 3}, \ 'Vortex center has to be defined in 3D or 2D or not at all!' if center is None: - center = (dim[1]/2, dim[2]/2) + center = (dim[1] / 2, dim[2] / 2) if axis == 'z': if len(center) == 3: # if a 3D-center is given, just take the x and y components center = (center[1], center[2]) - u = np.linspace(-center[1], dim[2]-1-center[1], dim[2]) + 0.5 # pixel center! - v = np.linspace(-center[0], dim[1]-1-center[0], dim[1]) + 0.5 # pixel center! + u = np.linspace(-center[1], dim[2] - 1 - center[1], dim[2]) + 0.5 # pixel center! + v = np.linspace(-center[0], dim[1] - 1 - center[0], dim[1]) + 0.5 # pixel center! uu, vv = np.meshgrid(u, v) - phi = np.expand_dims(np.arctan2(vv, uu)-pi/2, axis=0) + phi = np.expand_dims(np.arctan2(vv, uu) - pi / 2, axis=0) phi = np.tile(phi, (dim[0], 1, 1)) z_mag = np.zeros(dim) y_mag = -np.ones(dim) * np.sin(phi) * mag_shape * magnitude @@ -356,10 +357,10 @@ def create_mag_dist_vortex(mag_shape, center=None, axis='z', magnitude=1): elif axis == 'y': if len(center) == 3: # if a 3D-center is given, just take the x and z components center = (center[0], center[2]) - u = np.linspace(-center[1], dim[2]-1-center[1], dim[2]) + 0.5 # pixel center! - v = np.linspace(-center[0], dim[0]-1-center[0], dim[0]) + 0.5 # pixel center! + u = np.linspace(-center[1], dim[2] - 1 - center[1], dim[2]) + 0.5 # pixel center! + v = np.linspace(-center[0], dim[0] - 1 - center[0], dim[0]) + 0.5 # pixel center! uu, vv = np.meshgrid(u, v) - phi = np.expand_dims(np.arctan2(vv, uu)-pi/2, axis=1) + phi = np.expand_dims(np.arctan2(vv, uu) - pi / 2, axis=1) phi = np.tile(phi, (1, dim[1], 1)) z_mag = np.ones(dim) * np.sin(phi) * mag_shape * magnitude y_mag = np.zeros(dim) @@ -367,12 +368,14 @@ def create_mag_dist_vortex(mag_shape, center=None, axis='z', magnitude=1): elif axis == 'x': if len(center) == 3: # if a 3D-center is given, just take the z and y components center = (center[0], center[1]) - u = np.linspace(-center[1], dim[1]-1-center[1], dim[1]) + 0.5 # pixel center! - v = np.linspace(-center[0], dim[0]-1-center[0], dim[0]) + 0.5 # pixel center! + u = np.linspace(-center[1], dim[1] - 1 - center[1], dim[1]) + 0.5 # pixel center! + v = np.linspace(-center[0], dim[0] - 1 - center[0], dim[0]) + 0.5 # pixel center! uu, vv = np.meshgrid(u, v) - phi = np.expand_dims(np.arctan2(vv, uu)-pi/2, axis=2) + phi = np.expand_dims(np.arctan2(vv, uu) - pi / 2, axis=2) phi = np.tile(phi, (1, 1, dim[2])) z_mag = -np.ones(dim) * np.sin(phi) * mag_shape * magnitude y_mag = -np.ones(dim) * np.cos(phi) * mag_shape * magnitude x_mag = np.zeros(dim) + else: + raise ValueError('{} is not a valid argument (use x, y or z)'.format(axis)) return np.array([x_mag, y_mag, z_mag]) diff --git a/pyramid/magdata.py b/pyramid/magdata.py index 4e30445..a1359b4 100644 --- a/pyramid/magdata.py +++ b/pyramid/magdata.py @@ -43,22 +43,17 @@ class MagData(object): ---------- a: float The grid spacing in nm. - dim: tuple (N=3) - Dimensions (z, y, x) of the grid. magnitude: :class:`~numpy.ndarray` (N=4) The `x`-, `y`- and `z`-component of the magnetization vector for every 3D-gridpoint as a 4-dimensional numpy array (first dimension has to be 3, because of the 3 components). - mag_amp: :class:`~numpy.ndarray` (N=3) - The length (amplitude) of the magnetization vectors as a 3D-array. - mag_vec: :class:`~numpy.ndarray` (N=1) - Vector containing the magnetic distribution. """ - _log = logging.getLogger(__name__+'.MagData') + _log = logging.getLogger(__name__ + '.MagData') @property def a(self): + """The grid spacing in nm.""" return self._a @a.setter @@ -69,10 +64,12 @@ class MagData(object): @property def dim(self): + """Dimensions (z, y, x) of the grid.""" return self._dim @property def magnitude(self): + """The `x`-, `y`- and `z`-component of the magnetization vector for every 3D-gridpoint.""" return self._magnitude @magnitude.setter @@ -85,25 +82,27 @@ class MagData(object): @property def mag_amp(self): - return np.sqrt(np.sum(self.magnitude**2, axis=0)) + """The length (amplitude) of the magnetization vectors as a 3D-array.""" + return np.sqrt(np.sum(self.magnitude ** 2, axis=0)) @property def mag_vec(self): + """Vector containing the magnetic distribution.""" return np.reshape(self.magnitude, -1) @mag_vec.setter def mag_vec(self, mag_vec): mag_vec = np.asarray(mag_vec, dtype=fft.FLOAT) - assert np.size(mag_vec) == 3*np.prod(self.dim), \ + assert np.size(mag_vec) == 3 * np.prod(self.dim), \ 'Vector has to match magnitude dimensions! {} {}'.format(mag_vec.shape, - 3*np.prod(self.dim)) - self.magnitude = mag_vec.reshape((3,)+self.dim) + 3 * np.prod(self.dim)) + self.magnitude = mag_vec.reshape((3,) + self.dim) def __init__(self, a, magnitude): self._log.debug('Calling __init__') self.a = a self.magnitude = magnitude - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) def __repr__(self): self._log.debug('Calling __repr__') @@ -124,12 +123,12 @@ class MagData(object): if isinstance(other, MagData): self._log.debug('Adding two MagData objects') assert other.a == self.a, 'Added phase has to have the same grid spacing!' - assert other.magnitude.shape == (3,)+self.dim, \ + assert other.magnitude.shape == (3,) + self.dim, \ 'Added magnitude has to have the same dimensions!' - return MagData(self.a, self.magnitude+other.magnitude) + return MagData(self.a, self.magnitude + other.magnitude) else: # other is a Number self._log.debug('Adding an offset') - return MagData(self.a, self.magnitude+other) + return MagData(self.a, self.magnitude + other) def __sub__(self, other): # self - other self._log.debug('Calling __sub__') @@ -138,7 +137,7 @@ class MagData(object): def __mul__(self, other): # self * other self._log.debug('Calling __mul__') assert isinstance(other, Number), 'MagData objects can only be multiplied by numbers!' - return MagData(self.a, other*self.magnitude) + return MagData(self.a, other * self.magnitude) def __radd__(self, other): # other + self self._log.debug('Calling __radd__') @@ -165,23 +164,19 @@ class MagData(object): return self.__mul__(other) def copy(self): - '''Returns a copy of the :class:`~.MagData` object - - Parameters - ---------- - None + """Returns a copy of the :class:`~.MagData` object Returns ------- mag_data: :class:`~.MagData` A copy of the :class:`~.MagData`. - ''' + """ self._log.debug('Calling copy') return MagData(self.a, self.magnitude.copy()) def scale_down(self, n=1): - '''Scale down the magnetic distribution by averaging over two pixels along each axis. + """Scale down the magnetic distribution by averaging over two pixels along each axis. Parameters ---------- @@ -197,7 +192,7 @@ class MagData(object): Acts in place and changes dimensions and grid spacing accordingly. Only possible, if each axis length is a power of 2! - ''' + """ self._log.debug('Calling scale_down') assert n > 0 and isinstance(n, (int, long)), 'n must be a positive integer!' self.a *= 2 ** n @@ -208,11 +203,11 @@ class MagData(object): self.magnitude = np.pad(self.magnitude, ((0, 0), (0, pz), (0, py), (0, px)), mode='constant') # Create coarser grid for the magnetization: - self.magnitude = self.magnitude.reshape( - 3, self.dim[0]/2, 2, self.dim[1]/2, 2, self.dim[2]/2, 2).mean(axis=(6, 4, 2)) + shape_4d = (3, self.dim[0] / 2, 2, self.dim[1] / 2, 2, self.dim[2] / 2, 2) + self.magnitude = self.magnitude.reshape(shape_4d).mean(axis=(6, 4, 2)) def scale_up(self, n=1, order=0): - '''Scale up the magnetic distribution using spline interpolation of the requested order. + """Scale up the magnetic distribution using spline interpolation of the requested order. Parameters ---------- @@ -230,18 +225,18 @@ class MagData(object): Notes ----- Acts in place and changes dimensions and grid spacing accordingly. - ''' + """ self._log.debug('Calling scale_up') assert n > 0 and isinstance(n, (int, long)), 'n must be a positive integer!' assert 5 > order >= 0 and isinstance(order, (int, long)), \ 'order must be a positive integer between 0 and 5!' self.a /= 2 ** n - self.magnitude = np.array((zoom(self.magnitude[0], zoom=2**n, order=order), - zoom(self.magnitude[1], zoom=2**n, order=order), - zoom(self.magnitude[2], zoom=2**n, order=order))) + self.magnitude = np.array((zoom(self.magnitude[0], zoom=2 ** n, order=order), + zoom(self.magnitude[1], zoom=2 ** n, order=order), + zoom(self.magnitude[2], zoom=2 ** n, order=order))) def pad(self, pad_values): - '''Pad the current magnetic distribution with zeros for each individual axis. + """Pad the current magnetic distribution with zeros for each individual axis. Parameters ---------- @@ -257,19 +252,19 @@ class MagData(object): Notes ----- Acts in place and changes dimensions accordingly. - ''' + """ self._log.debug('Calling pad') assert len(pad_values) == 3, 'Pad values for each dimension have to be provided!' pv = np.zeros(6, dtype=np.int) for i, values in enumerate(pad_values): assert np.shape(values) in [(), (2,)], 'Only one or two values per axis can be given!' - pv[2*i:2*(i+1)] = values + pv[2 * i:2 * (i + 1)] = values self.magnitude = np.pad(self.magnitude, ((0, 0), (pv[0], pv[1]), (pv[2], pv[3]), (pv[4], pv[5])), mode='constant') def crop(self, crop_values): - '''Crop the current magnetic distribution with zeros for each individual axis. + """Crop the current magnetic distribution with zeros for each individual axis. Parameters ---------- @@ -285,19 +280,19 @@ class MagData(object): Notes ----- Acts in place and changes dimensions accordingly. - ''' + """ self._log.debug('Calling crop') assert len(crop_values) == 3, 'Crop values for each dimension have to be provided!' cv = np.zeros(6, dtype=np.int) for i, values in enumerate(crop_values): assert np.shape(values) in [(), (2,)], 'Only one or two values per axis can be given!' - cv[2*i:2*(i+1)] = values + cv[2 * i:2 * (i + 1)] = values cv *= np.resize([1, -1], len(cv)) cv = np.where(cv == 0, None, cv) self.magnitude = self.magnitude[:, cv[0]:cv[1], cv[2]:cv[3], cv[4]:cv[5]] def get_mask(self, threshold=0): - '''Mask all pixels where the amplitude of the magnetization lies above `threshold`. + """Mask all pixels where the amplitude of the magnetization lies above `threshold`. Parameters ---------- @@ -309,12 +304,12 @@ class MagData(object): mask : :class:`~numpy.ndarray` (N=3, boolean) Mask of the pixels where the amplitude of the magnetization lies above `threshold`. - ''' + """ self._log.debug('Calling get_mask') - return self.mag_amp > threshold + return np.where(self.mag_amp > threshold, True, False) def get_vector(self, mask): - '''Returns the magnetic components arranged in a vector, specified by a mask. + """Returns the magnetic components arranged in a vector, specified by a mask. Parameters ---------- @@ -327,7 +322,7 @@ class MagData(object): The vector containing magnetization components of the specified pixels. Order is: first all `x`-, then all `y`-, then all `z`-components. - ''' + """ self._log.debug('Calling get_vector') if mask is not None: return np.reshape([self.magnitude[0][mask], @@ -337,7 +332,7 @@ class MagData(object): return self.mag_vec def set_vector(self, vector, mask=None): - '''Set the magnetic components of the masked pixels to the values specified by `vector`. + """Set the magnetic components of the masked pixels to the values specified by `vector`. Parameters ---------- @@ -351,20 +346,20 @@ class MagData(object): ------- None - ''' + """ self._log.debug('Calling set_vector') vector = np.asarray(vector, dtype=fft.FLOAT) assert np.size(vector) % 3 == 0, 'Vector has to contain all 3 components for every pixel!' - count = np.size(vector)//3 + count = np.size(vector) // 3 if mask is not None: self.magnitude[0][mask] = vector[:count] # x-component - self.magnitude[1][mask] = vector[count:2*count] # y-component - self.magnitude[2][mask] = vector[2*count:] # z-component + self.magnitude[1][mask] = vector[count:2 * count] # y-component + self.magnitude[2][mask] = vector[2 * count:] # z-component else: self.mag_vec = vector def get_magslice(self, ax_slice=0, proj_axis='z', mode='complex'): - '''Extract a slice from the :class:`~.MagData` object. + """Extract a slice from the :class:`~.MagData` object. Parameters ---------- @@ -381,7 +376,7 @@ class MagData(object): mag_slice : :class:`~numpy.ndarray` (N=2) The extracted magnetization slice. - ''' + """ self._log.debug('Calling get_mag_slice') # Find slice: assert proj_axis == 'z' or proj_axis == 'y' or proj_axis == 'x', \ @@ -398,16 +393,18 @@ class MagData(object): self._log.debug('proj_axis == x') u_mag = np.swapaxes(np.copy(self.magnitude[2][..., ax_slice]), 0, 1) # z-component v_mag = np.swapaxes(np.copy(self.magnitude[1][..., ax_slice]), 0, 1) # y-component + else: + raise ValueError('{} is not a valid argument (use x, y or z)'.format(proj_axis)) # Create data field: if mode == 'complex': - return u_mag + 1j*v_mag + return u_mag + 1j * v_mag elif mode == 'amplitude': return np.hypot(u_mag, v_mag) else: raise ValueError('Given mode not understood!') def flip(self, axis='x'): - '''Flip/mirror the magnetization around the specified axis. + """Flip/mirror the magnetization around the specified axis. Parameters ---------- @@ -419,7 +416,7 @@ class MagData(object): mag_data_flip: :class:`~.MagData` A flipped copy of the :class:`~.MagData` object. - ''' + """ self._log.debug('Calling flip') if axis == 'x': mag_x, mag_y, mag_z = self.magnitude[:, :, :, ::-1] @@ -435,7 +432,7 @@ class MagData(object): return MagData(self.a, magnitude_flip) def rot90(self, axis='x'): - '''Rotate the magnetization 90° around the specified axis (right hand rotation). + """Rotate the magnetization 90° around the specified axis (right hand rotation). Parameters ---------- @@ -447,7 +444,7 @@ class MagData(object): mag_data_rot: :class:`~.MagData` A rotated copy of the :class:`~.MagData` object. - ''' + """ self._log.debug('Calling rot90') if axis == 'x': magnitude_rot = np.zeros((3, self.dim[1], self.dim[0], self.dim[2])) @@ -472,11 +469,7 @@ class MagData(object): return MagData(self.a, magnitude_rot) def to_signal(self): - '''Convert :class:`~.MagData` data into a HyperSpy signal. - - Parameters - ---------- - None + """Convert :class:`~.MagData` data into a HyperSpy signal. Returns ------- @@ -487,7 +480,7 @@ class MagData(object): ----- This method recquires the hyperspy package! - ''' + """ self._log.debug('Calling to_signal') # Try importing HyperSpy: if hs is None: @@ -514,7 +507,7 @@ class MagData(object): @classmethod def from_signal(cls, signal): - '''Convert a :class:`~hyperspy.signals.Signal` object to a :class:`~.MagData` object. + """Convert a :class:`~hyperspy.signals.Signal` object to a :class:`~.MagData` object. Parameters ---------- @@ -530,7 +523,7 @@ class MagData(object): ----- This method recquires the hyperspy package! - ''' + """ cls._log.debug('Calling from_signal') # Extract magnitude: magnitude = np.rollaxis(signal.data, 3, 0) @@ -539,7 +532,7 @@ class MagData(object): return cls(a, magnitude) def save_to_hdf5(self, filename='magdata.hdf5'): - '''Save magnetization data in a file with HyperSpys HDF5-format. + """Save magnetization data in a file with HyperSpys HDF5-format. Parameters ---------- @@ -551,7 +544,7 @@ class MagData(object): ------- None - ''' + """ self._log.debug('Calling save_to_hdf5') # Construct path if filename isn't already absolute: if not os.path.isabs(filename): @@ -561,11 +554,11 @@ class MagData(object): os.makedirs(directory) filename = os.path.join(directory, filename) # Save data to file: - self.to_signal.save(filename) + self.to_signal().save(filename) @classmethod def load_from_hdf5(cls, filename): - '''Construct :class:`~.MagData` object from HyperSpys HDF5-file. + """Construct :class:`~.MagData` object from HyperSpys HDF5-file. Parameters ---------- @@ -577,10 +570,10 @@ class MagData(object): mag_data: :class:`~.MagData` A :class:`~.MagData` object containing the loaded data. - ''' + """ cls._log.debug('Calling load_from_hdf5') if hs is None: - self._log.error('This method recquires the hyperspy package!') + cls._log.error('This method recquires the hyperspy package!') return # Use relative path if filename isn't already absolute: if not os.path.isabs(filename): @@ -591,7 +584,7 @@ class MagData(object): return MagData.from_signal(hs.load(filename)) def save_to_llg(self, filename='magdata.txt'): - '''Save magnetization data in a file with LLG-format. + """Save magnetization data in a file with LLG-format. Parameters ---------- @@ -603,11 +596,11 @@ class MagData(object): ------- None - ''' + """ self._log.debug('Calling save_to_llg') SCALE = 1.0E-9 / 1.0E-2 # from nm to cm # Create 3D meshgrid and reshape it and the magnetization into a list where x varies first: - zz, yy, xx = self.a * SCALE * (np.indices(self.dim)+0.5).reshape(3, -1) + zz, yy, xx = self.a * SCALE * (np.indices(self.dim) + 0.5).reshape(3, -1) x_vec, y_vec, z_vec = self.magnitude.reshape(3, -1) data = np.array([xx, yy, zz, x_vec, y_vec, z_vec]).T # Construct path if filename isn't already absolute: @@ -622,11 +615,11 @@ class MagData(object): mag_file.write('LLGFileCreator: %s\n' % filename) mag_file.write(' %d %d %d\n' % (self.dim[2], self.dim[1], self.dim[0])) mag_file.writelines('\n'.join(' '.join('{:7.6e}'.format(cell) - for cell in row) for row in data)) + for cell in row) for row in data)) @classmethod def load_from_llg(cls, filename): - '''Construct :class:`~.MagData` object from LLG-file. + """Construct :class:`~.MagData` object from LLG-file. Parameters ---------- @@ -638,7 +631,7 @@ class MagData(object): mag_data: :class:`~.MagData` A :class:`~.MagData` object containing the loaded data. - ''' + """ cls._log.debug('Calling load_from_llg') SCALE = 1.0E-9 / 1.0E-2 # From cm to nm # Use relative path if filename isn't already absolute: @@ -650,13 +643,13 @@ class MagData(object): data = np.genfromtxt(filename, skip_header=2) dim = tuple(np.genfromtxt(filename, dtype=int, skip_header=1, skip_footer=len(data[:, 0]))) a = (data[1, 0] - data[0, 0]) / SCALE - magnitude = data[:, 3:6].T.reshape((3,)+dim) + magnitude = data[:, 3:6].T.reshape((3,) + dim) return cls(a, magnitude) def quiver_plot(self, title='Magnetization Distribution', axis=None, proj_axis='z', coloring='angle', ar_dens=1, ax_slice=None, log=False, scaled=True, scale=1., show_mask=True): - '''Plot a slice of the magnetization as a quiver plot. + """Plot a slice of the magnetization as a quiver plot. Parameters ---------- @@ -689,7 +682,7 @@ class MagData(object): axis: :class:`~matplotlib.axes.AxesSubplot` The axis on which the graph is plotted. - ''' + """ self._log.debug('Calling quiver_plot') assert proj_axis == 'z' or proj_axis == 'y' or proj_axis == 'x', \ 'Axis has to be x, y or z (as string).' @@ -723,6 +716,8 @@ class MagData(object): u_label = 'z [px]' v_label = 'y [px]' submask = self.get_mask()[..., ax_slice] + else: + raise ValueError('{} is not a valid argument (use x, y or z)'.format(proj_axis)) # Prepare quiver (select only used arrows if ar_dens is specified): dim_uv = plot_u.shape vv, uu = np.indices(dim_uv) + 0.5 # shift to center of pixel @@ -731,11 +726,11 @@ class MagData(object): plot_u = plot_u[::ar_dens, ::ar_dens] plot_v = plot_v[::ar_dens, ::ar_dens] amplitudes = np.hypot(plot_u, plot_v) - angles = np.angle(plot_u+1j*plot_v, deg=True).tolist() + angles = np.angle(plot_u + 1j * plot_v, deg=True).tolist() # Calculate the arrow colors: if coloring == 'angle': self._log.debug('Encoding angles') - colorinds = (1 + np.arctan2(plot_v, plot_u)/np.pi) / 2 # in-plane color index (0 - 1) + colorinds = (1 + np.arctan2(plot_v, plot_u) / np.pi) / 2 # in-plane color index (0-1). cmap = DirectionalColormap() elif coloring == 'amplitude': self._log.debug('Encoding amplitude') @@ -759,16 +754,16 @@ class MagData(object): amp = np.round(amplitudes, decimals=cutoff) min_value = amp[np.nonzero(amp)].min() plot_u = np.round(plot_u, decimals=cutoff) / min_value - plot_u = np.log10(np.abs(plot_u)+1) * np.sign(plot_u) + plot_u = np.log10(np.abs(plot_u) + 1) * np.sign(plot_u) plot_v = np.round(plot_v, decimals=cutoff) / min_value - plot_v = np.log10(np.abs(plot_v)+1) * np.sign(plot_v) + plot_v = np.log10(np.abs(plot_v) + 1) * np.sign(plot_v) amplitudes = np.hypot(plot_u, plot_v) # Recalculate! # Scale the magnitude of the arrows to the highest one (if specified): if scaled: plot_u /= amplitudes.max() + 1E-30 plot_v /= amplitudes.max() + 1E-30 axis.quiver(uu, vv, plot_u, plot_v, colorinds, cmap=cmap, clim=(0, 1), angles=angles, - pivot='middle', units='xy', scale_units='xy', scale=scale/ar_dens, + pivot='middle', units='xy', scale_units='xy', scale=scale / ar_dens, minlength=0.25, headwidth=6, headlength=7) if show_mask and not np.all(submask): # Plot mask if desired and not trivial! vv, uu = np.indices(dim_uv) + 0.5 # shift to center of pixel @@ -780,9 +775,9 @@ class MagData(object): axis.set_ylabel(v_label, fontsize=15) axis.tick_params(axis='both', which='major', labelsize=14) if dim_uv[0] >= dim_uv[1]: - u_bin, v_bin = np.max((2, np.floor(9*dim_uv[1]/dim_uv[0]))), 9 + u_bin, v_bin = np.max((2, np.floor(9 * dim_uv[1] / dim_uv[0]))), 9 else: - u_bin, v_bin = 9, np.max((2, np.floor(9*dim_uv[0]/dim_uv[1]))) + u_bin, v_bin = 9, np.max((2, np.floor(9 * dim_uv[0] / dim_uv[1]))) axis.xaxis.set_major_locator(MaxNLocator(nbins=u_bin, integer=True)) axis.yaxis.set_major_locator(MaxNLocator(nbins=v_bin, integer=True)) # Return plotting axis: @@ -790,7 +785,7 @@ class MagData(object): def quiver_plot3d(self, title='Magnetization Distribution', limit=None, cmap='jet', ar_dens=1, mode='arrow', coloring='angle', show_pipeline=False): - '''Plot the magnetization as 3D-vectors in a quiverplot. + """Plot the magnetization as 3D-vectors in a quiverplot. Parameters ---------- @@ -817,7 +812,7 @@ class MagData(object): plot : :class:`mayavi.modules.vectors.Vectors` The plot object. - ''' + """ self._log.debug('Calling quiver_plot3D') from mayavi import mlab a = self.a @@ -826,7 +821,7 @@ class MagData(object): limit = np.max(self.mag_amp) ad = ar_dens # Create points and vector components as lists: - zz, yy, xx = (np.indices(dim)-a/2).reshape((3,)+dim) + zz, yy, xx = (np.indices(dim) - a / 2).reshape((3,) + dim) zz = zz[::ad, ::ad, ::ad].flatten() yy = yy[::ad, ::ad, ::ad].flatten() xx = xx[::ad, ::ad, ::ad].flatten() @@ -840,7 +835,7 @@ class MagData(object): self._log.debug('Encoding full 3D angles') from tvtk.api import tvtk rgb = DirectionalColormap.rgb_from_direction(x_mag, y_mag, z_mag) - colors = map(tuple, rgb) # convert to list of tuples! + colors = [tuple(c) for c in rgb] # convert to list of tuples! sc = tvtk.UnsignedCharArray() # Used to hold the colors sc.from_array(colors) plot.mlab_source.dataset.point_data.scalars = sc diff --git a/pyramid/phasemap.py b/pyramid/phasemap.py index 1e475fc..f5b8aba 100644 --- a/pyramid/phasemap.py +++ b/pyramid/phasemap.py @@ -8,10 +8,10 @@ import logging import os from numbers import Number -import matplotlib as mpl import matplotlib.pyplot as plt import numpy as np from PIL import Image +from matplotlib.colors import LinearSegmentedColormap from matplotlib.ticker import MaxNLocator, FuncFormatter from mpl_toolkits.mplot3d import Axes3D from scipy.ndimage.interpolation import zoom @@ -29,8 +29,7 @@ __all__ = ['PhaseMap'] class PhaseMap(object): - - '''Class for storing phase map data. + """Class for storing phase map data. Represents 2-dimensional phase maps. The phase information itself is stored as a 2-dimensional matrix in `phase`, but can also be accessed as a vector via `phase_vec`. :class:`~.PhaseMap` @@ -48,12 +47,8 @@ class PhaseMap(object): ---------- a: float The grid spacing in nm. - dim_uv: tuple (N=2) - Dimensions of the grid. phase: :class:`~numpy.ndarray` (N=2) - Matrix containing the phase shift. - phase_vec: :class:`~numpy.ndarray` (N=2) - Vector containing the phase shift. + Array containing the phase shift. mask: :class:`~numpy.ndarray` (boolean, N=2, optional) Mask which determines the projected magnetization distribution, gotten from MIP images or otherwise acquired. Defaults to an array of ones (all pixels are considered). @@ -66,7 +61,7 @@ class PhaseMap(object): because the phase is scaled accordingly. Does not change the phase itself, which is always in `rad`. - ''' + """ _log = logging.getLogger(__name__) @@ -110,11 +105,12 @@ class PhaseMap(object): (0.75, 1.0, 1.0), (1.00, 0.0, 0.0)]} - HOLO_CMAP = mpl.colors.LinearSegmentedColormap('my_colormap', CDICT, 256) - HOLO_CMAP_INV = mpl.colors.LinearSegmentedColormap('my_colormap', CDICT_INV, 256) + HOLO_CMAP = LinearSegmentedColormap('my_colormap', CDICT, 256) + HOLO_CMAP_INV = LinearSegmentedColormap('my_colormap', CDICT_INV, 256) @property def a(self): + """Grid spacing in nm.""" return self._a @a.setter @@ -125,10 +121,12 @@ class PhaseMap(object): @property def dim_uv(self): + """Dimensions of the grid.""" return self._dim_uv @property def phase(self): + """Array containing the phase shift.""" return self._phase @phase.setter @@ -140,6 +138,7 @@ class PhaseMap(object): @property def phase_vec(self): + """Vector containing the phase shift.""" return np.reshape(self.phase, -1) @phase_vec.setter @@ -150,6 +149,7 @@ class PhaseMap(object): @property def mask(self): + """Mask which determines the projected magnetization distribution""" return self._mask @mask.setter @@ -162,6 +162,7 @@ class PhaseMap(object): @property def confidence(self): + """Confidence array which determines the trust of specific regions of the phase_map.""" return self._confidence @confidence.setter @@ -175,6 +176,7 @@ class PhaseMap(object): @property def unit(self): + """The unit of the phase map. Default is `rad`.""" return self._unit @unit.setter @@ -189,12 +191,12 @@ class PhaseMap(object): self.mask = mask self.confidence = confidence self.unit = unit - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) def __repr__(self): self._log.debug('Calling __repr__') return '%s(a=%r, phase=%r, mask=%r, confidence=%r, unit=%r)' % \ - (self.__class__, self.a, self.phase, self.mask, self.confidence, self.unit) + (self.__class__, self.a, self.phase, self.mask, self.confidence, self.unit) def __str__(self): self._log.debug('Calling __str__') @@ -215,10 +217,10 @@ class PhaseMap(object): 'Added magnitude has to have the same dimensions!' mask_comb = np.logical_or(self.mask, other.mask) # masks combine conf_comb = (self.confidence + other.confidence) / 2 # confidence averaged! - return PhaseMap(self.a, self.phase+other.phase, mask_comb, conf_comb, self.unit) + return PhaseMap(self.a, self.phase + other.phase, mask_comb, conf_comb, self.unit) else: # other is a Number self._log.debug('Adding an offset') - return PhaseMap(self.a, self.phase+other, self.mask, self.confidence, self.unit) + return PhaseMap(self.a, self.phase + other, self.mask, self.confidence, self.unit) def __sub__(self, other): # self - other self._log.debug('Calling __sub__') @@ -229,7 +231,7 @@ class PhaseMap(object): assert (isinstance(other, Number) or (isinstance(other, np.ndarray) and other.shape == self.dim_uv)), \ 'PhaseMap objects can only be multiplied by scalar numbers or fitting arrays!' - return PhaseMap(self.a, other*self.phase, self.mask, self.confidence, self.unit) + return PhaseMap(self.a, other * self.phase, self.mask, self.confidence, self.unit) def __radd__(self, other): # other + self self._log.debug('Calling __radd__') @@ -256,24 +258,20 @@ class PhaseMap(object): return self.__mul__(other) def copy(self): - '''Returns a copy of the :class:`~.PhaseMap` object - - Parameters - ---------- - None + """Returns a copy of the :class:`~.PhaseMap` object Returns ------- phase_map: :class:`~.PhaseMap` A copy of the :class:`~.PhaseMap`. - ''' + """ self._log.debug('Calling copy') return PhaseMap(self.a, self.phase.copy(), self.mask.copy(), self.confidence.copy(), self.unit) def scale_down(self, n=1): - '''Scale down the phase map by averaging over two pixels along each axis. + """Scale down the phase map by averaging over two pixels along each axis. Parameters ---------- @@ -289,7 +287,7 @@ class PhaseMap(object): Acts in place and changes dimensions and grid spacing accordingly. Only possible, if each axis length is a power of 2! - ''' + """ self._log.debug('Calling scale_down') assert n > 0 and isinstance(n, (int, long)), 'n must be a positive integer!' self.a *= 2 ** n @@ -300,14 +298,14 @@ class PhaseMap(object): self.phase = np.pad(self.phase, ((0, pv), (0, pu)), mode='constant') # Create coarser grid for the magnetization: dim_uv = self.dim_uv - self.phase = self.phase.reshape(dim_uv[0]/2, 2, dim_uv[1]/2, 2).mean(axis=(3, 1)) - mask = self.mask.reshape(dim_uv[0]/2, 2, dim_uv[1]/2, 2) + self.phase = self.phase.reshape((dim_uv[0] / 2, 2, dim_uv[1] / 2, 2)).mean(axis=(3, 1)) + mask = self.mask.reshape(dim_uv[0] / 2, 2, dim_uv[1] / 2, 2) self.mask = mask[:, 0, :, 0] & mask[:, 1, :, 0] & mask[:, 0, :, 1] & mask[:, 1, :, 1] - self.confidence = self.confidence.reshape(dim_uv[0]/2, 2, - dim_uv[1]/2, 2).mean(axis=(3, 1)) + self.confidence = self.confidence.reshape(dim_uv[0] / 2, 2, + dim_uv[1] / 2, 2).mean(axis=(3, 1)) def scale_up(self, n=1, order=0): - '''Scale up the phase map using spline interpolation of the requested order. + """Scale up the phase map using spline interpolation of the requested order. Parameters ---------- @@ -326,18 +324,18 @@ class PhaseMap(object): ----- Acts in place and changes dimensions and grid spacing accordingly. - ''' + """ self._log.debug('Calling scale_up') assert n > 0 and isinstance(n, (int, long)), 'n must be a positive integer!' assert 5 > order >= 0 and isinstance(order, (int, long)), \ 'order must be a positive integer between 0 and 5!' self.a /= 2 ** n - self.phase = zoom(self.phase, zoom=2**n, order=order) - self.mask = zoom(self.mask, zoom=2**n, order=0) - self.confidence = zoom(self.confidence, zoom=2**n, order=order) + self.phase = zoom(self.phase, zoom=2 ** n, order=order) + self.mask = zoom(self.mask, zoom=2 ** n, order=0) + self.confidence = zoom(self.confidence, zoom=2 ** n, order=order) def pad(self, pad_values, masked=True): - '''Pad the current phase map with zeros for each individual axis. + """Pad the current phase map with zeros for each individual axis. Parameters ---------- @@ -358,13 +356,13 @@ class PhaseMap(object): Acts in place and changes dimensions accordingly. The confidence of the padded areas is set to zero! - ''' + """ self._log.debug('Calling pad') assert len(pad_values) == 2, 'Pad values for each dimension have to be provided!' pv = np.zeros(4, dtype=np.int) for i, values in enumerate(pad_values): assert np.shape(values) in [(), (2,)], 'Only one or two values per axis can be given!' - pv[2*i:2*(i+1)] = values + pv[2 * i:2 * (i + 1)] = values self.phase = np.pad(self.phase, ((pv[0], pv[1]), (pv[2], pv[3])), mode='constant') self.mask = np.pad(self.mask, ((pv[0], pv[1]), (pv[2], pv[3])), mode='constant', constant_values=masked) @@ -372,7 +370,7 @@ class PhaseMap(object): mode='constant') def crop(self, crop_values): - '''Pad the current phase map with zeros for each individual axis. + """Pad the current phase map with zeros for each individual axis. Parameters ---------- @@ -380,9 +378,6 @@ class PhaseMap(object): Number of zeros which should be cropped. Provided as a tuple where each entry corresponds to an axis. An entry can be one int (same cropping for both sides) or again a tuple which specifies the crop values for both sides of the corresponding axis. - masked: boolean - Determines if the padded areas should be masked or not. Defaults to `True` and thus - creates a 'buffer zone' for the magnetization distribution in the reconstruction. Returns ------- @@ -392,13 +387,13 @@ class PhaseMap(object): ----- Acts in place and changes dimensions accordingly. - ''' + """ self._log.debug('Calling crop') assert len(crop_values) == 2, 'Crop values for each dimension have to be provided!' cv = np.zeros(4, dtype=np.int) for i, values in enumerate(crop_values): assert np.shape(values) in [(), (2,)], 'Only one or two values per axis can be given!' - cv[2*i:2*(i+1)] = values + cv[2 * i:2 * (i + 1)] = values cv *= np.resize([1, -1], len(cv)) cv = np.where(cv == 0, None, cv) self.phase = self.phase[cv[0]:cv[1], cv[2]:cv[3]] @@ -406,11 +401,7 @@ class PhaseMap(object): self.confidence = self.confidence[cv[0]:cv[1], cv[2]:cv[3]] def to_signal(self): - '''Convert :class:`~.PhaseMap` data into a HyperSpy Image. - - Parameters - ---------- - None + """Convert :class:`~.PhaseMap` data into a HyperSpy Image. Returns ------- @@ -421,7 +412,7 @@ class PhaseMap(object): ----- This method recquires the hyperspy package! - ''' + """ self._log.debug('Calling to_signal') if hs is None: self._log.error('This method recquires the hyperspy package!') @@ -445,7 +436,7 @@ class PhaseMap(object): @classmethod def from_signal(cls, signal): - '''Convert a :class:`~hyperspy.signals.Image` object to a :class:`~.PhaseMap` object. + """Convert a :class:`~hyperspy.signals.Image` object to a :class:`~.PhaseMap` object. Parameters ---------- @@ -461,7 +452,7 @@ class PhaseMap(object): ----- This method recquires the hyperspy package! - ''' + """ cls._log.debug('Calling from_signal') # Extract phase: phase = signal.data @@ -504,7 +495,7 @@ class PhaseMap(object): @classmethod def load_from_hdf5(cls, filename): - '''Construct :class:`~.DataMag` object from HyperSpys HDF5-file. + """Construct :class:`~.DataMag` object from HyperSpys HDF5-file. Parameters ---------- @@ -516,7 +507,7 @@ class PhaseMap(object): mag_data: :class:`~.MagData` A :class:`~.MagData` object containing the loaded data. - ''' + """ cls._log.debug('Calling load_from_hdf5') if hs is None: cls._log.error('This method recquires the hyperspy package!') @@ -530,7 +521,7 @@ class PhaseMap(object): return PhaseMap.from_signal(hs.load(filename)) def save_to_txt(self, filename='phasemap.txt', skip_header=False): - '''Save :class:`~.PhaseMap` data in a file with txt-format. + """Save :class:`~.PhaseMap` data in a file with txt-format. Parameters ---------- @@ -545,7 +536,7 @@ class PhaseMap(object): ------- None - ''' + """ self._log.debug('Calling save_to_txt') # Construct path if filename isn't already absolute: if not os.path.isabs(filename): @@ -563,7 +554,7 @@ class PhaseMap(object): @classmethod def load_from_txt(cls, filename): - '''Construct :class:`~.PhaseMap` object from a human readable txt-file. + """Construct :class:`~.PhaseMap` object from a human readable txt-file. Parameters ---------- @@ -580,7 +571,7 @@ class PhaseMap(object): Does not recover the mask, confidence or unit of the original phase map, which default to `None`, `None` and `'rad'`, respectively. - ''' + """ cls._log.debug('Calling load_from_txt') # Use relative path if filename isn't already absolute: if not os.path.isabs(filename): @@ -596,7 +587,7 @@ class PhaseMap(object): def display_phase(self, title='Phase Map', cmap='RdBu', limit=None, norm=None, axis=None, cbar=True, show_mask=True, show_conf=True): - '''Display the phasemap as a colormesh. + """Display the phasemap as a colormesh. Parameters ---------- @@ -624,7 +615,7 @@ class PhaseMap(object): axis, cbar: :class:`~matplotlib.axes.AxesSubplot` The axis on which the graph is plotted and the colorbar. - ''' + """ self._log.debug('Calling display_phase') # Take units into consideration: phase = self.phase * self.UNITDICT[self.unit] @@ -639,20 +630,20 @@ class PhaseMap(object): im = axis.pcolormesh(phase, cmap=cmap, vmin=-limit, vmax=limit, norm=norm) if show_mask or show_conf: vv, uu = np.indices(self.dim_uv) + 0.5 - if show_mask and not np.all(self.mask): # Plot mask if desired and not trivial! - axis.contour(uu, vv, self.mask, levels=[0.5], colors='k', linestyles='dotted') - if show_conf and not np.all(self.confidence == 1.0): - vv, uu = np.indices(self.dim_uv) + 0.5 - axis.pcolormesh(self.confidence, cmap=TransparentColormap(0.2, 0.3, 0.2, [0.2, 0.])) + if show_mask and not np.all(self.mask): # Plot mask if desired and not trivial! + axis.contour(uu, vv, self.mask, levels=[0.5], colors='k', linestyles='dotted') + if show_conf and not np.all(self.confidence == 1.0): + colormap = TransparentColormap(0.2, 0.3, 0.2, [0.2, 0.]) + axis.pcolormesh(self.confidence, cmap=colormap) # Set the axes ticks and labels: if self.dim_uv[0] >= self.dim_uv[1]: - u_bin, v_bin = np.max((2, np.floor(9*self.dim_uv[1]/self.dim_uv[0]))), 9 + u_bin, v_bin = np.max((2, np.floor(9 * self.dim_uv[1] / self.dim_uv[0]))), 9 else: - u_bin, v_bin = 9, np.max((2, np.floor(9*self.dim_uv[0]/self.dim_uv[1]))) + u_bin, v_bin = 9, np.max((2, np.floor(9 * self.dim_uv[0] / self.dim_uv[1]))) axis.xaxis.set_major_locator(MaxNLocator(nbins=u_bin, integer=True)) axis.yaxis.set_major_locator(MaxNLocator(nbins=v_bin, integer=True)) - axis.xaxis.set_major_formatter(FuncFormatter(lambda x, pos: '{:g}'.format(x*self.a))) - axis.yaxis.set_major_formatter(FuncFormatter(lambda x, pos: '{:g}'.format(x*self.a))) + axis.xaxis.set_major_formatter(FuncFormatter(lambda x, pos: '{:g}'.format(x * self.a))) + axis.yaxis.set_major_formatter(FuncFormatter(lambda x, pos: '{:g}'.format(x * self.a))) axis.tick_params(axis='both', which='major', labelsize=14) axis.set_title(title, fontsize=18) axis.set_xlim(0, self.dim_uv[1]) @@ -671,7 +662,7 @@ class PhaseMap(object): return axis def display_phase3d(self, title='Phase Map', cmap='RdBu'): - '''Display the phasemap as a 3-D surface with contourplots. + """Display the phasemap as a 3-D surface with contourplots. Parameters ---------- @@ -686,7 +677,7 @@ class PhaseMap(object): axis: :class:`~matplotlib.axes.AxesSubplot` The axis on which the graph is plotted. - ''' + """ self._log.debug('Calling display_phase3d') # Take units into consideration: phase = self.phase * self.UNITDICT[self.unit] @@ -698,6 +689,7 @@ class PhaseMap(object): axis.plot_surface(uu, vv, phase, rstride=4, cstride=4, alpha=0.7, cmap=cmap, linewidth=0, antialiased=False) axis.contourf(uu, vv, phase, 15, zdir='z', offset=np.min(phase), cmap=cmap) + axis.set_title(title) axis.view_init(45, -135) axis.set_xlabel('u-axis [px]') axis.set_ylabel('v-axis [px]') @@ -707,7 +699,7 @@ class PhaseMap(object): def display_holo(self, title=None, gain='auto', axis=None, grad_encode='bright', interpolation='none'): - '''Display the color coded holography image. + """Display the color coded holography image. Parameters ---------- @@ -725,29 +717,30 @@ class PhaseMap(object): the gradient strength with color saturation. interpolation : {'none, 'bilinear', 'cubic', 'nearest'}, optional Defines the interpolation method. No interpolation is used in the default case. - show: bool, optional - A switch which determines if the plot is shown at the end of plotting. Default is True. Returns ------- axis: :class:`~matplotlib.axes.AxesSubplot` The axis on which the graph is plotted. - ''' + """ self._log.debug('Calling display_holo') # Calculate gain if 'auto' is selected: if gain == 'auto': - gain = 4 * 2*np.pi/(np.abs(self.phase).max()+1E-30) + gain = 4 * 2 * np.pi / (np.abs(self.phase).max() + 1E-30) # Set title if not set: if title is None: title = 'Contour Map (gain: %.2g)' % gain # Calculate the holography image intensity: - holo = (1 + np.cos(gain * self.phase)) / 2 + holo = np.cos(gain * self.phase) + holo += 1 # Shift to positive values + holo /= 2 # Rescale to [0, 1] # Calculate the phase gradients, expressed by magnitude and angle: phase_grad_x, phase_grad_y = np.gradient(self.phase, self.a, self.a) - angles = (1 - np.arctan2(phase_grad_y, phase_grad_x)/np.pi) / 2 + angles = (1 - np.arctan2(phase_grad_y, phase_grad_x) / np.pi) / 2 phase_grad_amp = np.hypot(phase_grad_y, phase_grad_x) - saturations = np.sin(phase_grad_amp/(phase_grad_amp.max()+1E-30)*np.pi/2) # betw. 0 and 1 + saturations = np.sin( + phase_grad_amp / (phase_grad_amp.max() + 1E-30) * np.pi / 2) # betw. 0 and 1 # Calculate color encoding: if grad_encode == 'dark': pass @@ -756,7 +749,7 @@ class PhaseMap(object): elif grad_encode == 'color': saturations = np.ones_like(saturations) elif grad_encode == 'none': - saturations = 2*np.ones_like(saturations) + saturations = 2 * np.ones_like(saturations) else: raise AssertionError('Gradient encoding not recognized!') # Calculate colored holo image: @@ -778,9 +771,9 @@ class PhaseMap(object): axis.set_xlabel('u-axis [px]', fontsize=15) axis.set_ylabel('v-axis [px]', fontsize=15) if self.dim_uv[0] >= self.dim_uv[1]: - u_bin, v_bin = np.max((2, np.floor(9*self.dim_uv[1]/self.dim_uv[0]))), 9 + u_bin, v_bin = np.max((2, np.floor(9 * self.dim_uv[1] / self.dim_uv[0]))), 9 else: - u_bin, v_bin = 9, np.max((2, np.floor(9*self.dim_uv[0]/self.dim_uv[1]))) + u_bin, v_bin = 9, np.max((2, np.floor(9 * self.dim_uv[0] / self.dim_uv[1]))) axis.xaxis.set_major_locator(MaxNLocator(nbins=u_bin, integer=True)) axis.yaxis.set_major_locator(MaxNLocator(nbins=v_bin, integer=True)) # Return plotting axis: @@ -789,7 +782,7 @@ class PhaseMap(object): def display_combined(self, title='Combined Plot', cmap='RdBu', limit=None, norm=None, gain='auto', interpolation='none', grad_encode='bright', cbar=True, show_mask=True, show_conf=True): - '''Display the phase map and the resulting color coded holography image in one plot. + """Display the phase map and the resulting color coded holography image in one plot. Parameters ---------- @@ -827,7 +820,7 @@ class PhaseMap(object): phase_axis, holo_axis: :class:`~matplotlib.axes.AxesSubplot` The axes on which the graphs are plotted. - ''' + """ self._log.debug('Calling display_combined') # Create combined plot and set title: fig = plt.figure(figsize=(15, 7)) @@ -839,7 +832,7 @@ class PhaseMap(object): # Plot phase map: phase_axis = fig.add_subplot(1, 2, 2, aspect='equal') fig.subplots_adjust(right=0.85) - self.display_phase(cmap='RdBu', limit=limit, norm=norm, axis=phase_axis, + self.display_phase(cmap=cmap, limit=limit, norm=norm, axis=phase_axis, cbar=cbar, show_mask=show_mask, show_conf=show_conf) # Return the plotting axes: return phase_axis, holo_axis diff --git a/pyramid/phasemapper.py b/pyramid/phasemapper.py index 7a97fbe..9a360fb 100644 --- a/pyramid/phasemapper.py +++ b/pyramid/phasemapper.py @@ -7,34 +7,31 @@ a given projection of a 3-dimensional magnetic distribution (see :mod:`~pyramid. For the magnetic phase map, an approach using real space and one using Fourier space is provided. The electrostatic contribution is calculated by using the assumption of a mean inner potential.""" +import abc +import logging import numpy as np +import pyramid.numcore.phasemapper_core as nc from numpy import pi -import abc -import pyramid.numcore.phasemapper_core as nc +from pyramid import fft +from pyramid.kernel import Kernel from pyramid.magdata import MagData from pyramid.phasemap import PhaseMap from pyramid.projector import SimpleProjector -from pyramid.kernel import Kernel -from pyramid import fft - -import logging - __all__ = ['PhaseMapperRDFC', 'PhaseMapperRDRC', 'PhaseMapperFDFC', 'pm'] _log = logging.getLogger(__name__) -PHI_0 = 2067.83 # magnetic flux in T*nm² +PHI_0 = 2067.83 # magnetic flux in T*nm² H_BAR = 6.626E-34 # Planck constant in J*s -M_E = 9.109E-31 # electron mass in kg -Q_E = 1.602E-19 # electron charge in C -C = 2.998E8 # speed of light in m/s +M_E = 9.109E-31 # electron mass in kg +Q_E = 1.602E-19 # electron charge in C +C = 2.998E8 # speed of light in m/s class PhaseMapper(object): - - '''Abstract base class for the phase calculation from a 2-dimensional distribution. + """Abstract base class for the phase calculation from a 2-dimensional distribution. The :class:`~.PhaseMapper-` class represents a strategy for the phasemapping of a 2-dimensional magnetic distribution with two components onto a scalar phase map. @@ -43,27 +40,56 @@ class PhaseMapper(object): can be called as a function and take a :class:`~.MagData` object as input and return a :class:`~.PhaseMap` object. - ''' + """ __metaclass__ = abc.ABCMeta - _log = logging.getLogger(__name__+'.PhaseMapper') + _log = logging.getLogger(__name__ + '.PhaseMapper') @abc.abstractmethod - def __call__(self, mag_data, offset=None): + def __call__(self, mag_data): raise NotImplementedError() @abc.abstractmethod - def jac_dot(self, vector, offset=None): + def jac_dot(self, vector): + """Calculate the product of the Jacobi matrix with a given `vector`. + + Parameters + ---------- + vector : :class:`~numpy.ndarray` (N=1) + Vectorized form of the magnetization in `u`- and `v`-direction of every pixel + (row-wise). The first ``N**2`` elements have to correspond to the `u`-, the next + ``N**2`` elements to the `v`-component of the magnetization. + + Returns + ------- + result : :class:`~numpy.ndarray` (N=1) + Product of the Jacobi matrix (which is not explicitely calculated) with the vector. + + """ raise NotImplementedError() @abc.abstractmethod - def jac_T_dot(self, vector, offset=None): + def jac_T_dot(self, vector): + """Calculate the product of the transposed Jacobi matrix with a given `vector`. + + Parameters + ---------- + vector : :class:`~numpy.ndarray` (N=1) + Vector with ``N**2`` entries which represents a matrix with dimensions like a scalar + phasemap. + + Returns + ------- + result : :class:`~numpy.ndarray` (N=1) + Product of the transposed Jacobi matrix (which is not explicitely calculated) with + the vector, which has ``2*N**2`` entries like a 2D magnetic projection. + + """ raise NotImplementedError() class PhaseMapperRDFC(PhaseMapper): - - '''Class representing a phase mapping strategy using real space discretization and Fourier + """Class representing a phase mapping strategy using real space discretization and Fourier space convolution. The :class:`~.PMConvolve` class represents a phase mapping strategy involving discretization in @@ -72,16 +98,16 @@ class PhaseMapperRDFC(PhaseMapper): Attributes ---------- - a : float - The grid spacing in nm. + kernel : :class:`~pyramid.Kernel` + Convolution kernel, representing the phase contribution of one single magnetized pixel. m: int Size of the image space. n: int Size of the input space. - ''' + """ - _log = logging.getLogger(__name__+'.PhaseMapperRDFC') + _log = logging.getLogger(__name__ + '.PhaseMapperRDFC') def __init__(self, kernel): self._log.debug('Calling __init__') @@ -91,7 +117,7 @@ class PhaseMapperRDFC(PhaseMapper): self.u_mag = fft.zeros(kernel.dim_pad, dtype=fft.FLOAT) self.v_mag = fft.zeros(kernel.dim_pad, dtype=fft.FLOAT) self.mag_adj = fft.zeros(kernel.dim_pad, dtype=fft.FLOAT) - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) def __repr__(self): self._log.debug('Calling __repr__') @@ -99,7 +125,7 @@ class PhaseMapperRDFC(PhaseMapper): def __str__(self): self._log.debug('Calling __str__') - return 'PhaseMapperRDFC(kernel=%s)' % (self.kernel) + return 'PhaseMapperRDFC(kernel=%s)' % self.kernel def __call__(self, mag_data): assert isinstance(mag_data, MagData), 'Only MagData objects can be mapped!' @@ -116,12 +142,12 @@ class PhaseMapperRDFC(PhaseMapper): self.u_mag_fft = fft.rfftn(self.u_mag) self.v_mag_fft = fft.rfftn(self.v_mag) # Convolve the magnetization with the kernel in Fourier space: - self.phase_fft = self.u_mag_fft*self.kernel.u_fft - self.v_mag_fft*self.kernel.v_fft + self.phase_fft = self.u_mag_fft * self.kernel.u_fft - self.v_mag_fft * self.kernel.v_fft # Return the result: return fft.irfftn(self.phase_fft)[self.kernel.slice_phase] def jac_dot(self, vector): - '''Calculate the product of the Jacobi matrix with a given `vector`. + """Calculate the product of the Jacobi matrix with a given `vector`. Parameters ---------- @@ -135,15 +161,15 @@ class PhaseMapperRDFC(PhaseMapper): result : :class:`~numpy.ndarray` (N=1) Product of the Jacobi matrix (which is not explicitely calculated) with the vector. - ''' + """ assert len(vector) == self.n, \ 'vector size not compatible! vector: {}, size: {}'.format(len(vector), self.n) self.u_mag[self.kernel.slice_mag], self.v_mag[self.kernel.slice_mag] = \ - np.reshape(vector, (2,)+self.kernel.dim_uv) + np.reshape(vector, (2,) + self.kernel.dim_uv) return np.ravel(self._convolve()) def jac_T_dot(self, vector): - '''Calculate the product of the transposed Jacobi matrix with a given `vector`. + """Calculate the product of the transposed Jacobi matrix with a given `vector`. Parameters ---------- @@ -157,7 +183,7 @@ class PhaseMapperRDFC(PhaseMapper): Product of the transposed Jacobi matrix (which is not explicitely calculated) with the vector, which has ``2*N**2`` entries like a 2D magnetic projection. - ''' + """ assert len(vector) == self.m, \ 'vector size not compatible! vector: {}, size: {}'.format(len(vector), self.m) self.mag_adj[self.kernel.slice_mag] = vector.reshape(self.kernel.dim_uv) @@ -172,8 +198,7 @@ class PhaseMapperRDFC(PhaseMapper): class PhaseMapperRDRC(PhaseMapper): - - '''Class representing a phase mapping strategy using real space discretization. + """Class representing a phase mapping strategy using real space discretization. The :class:`~.PMReal` class represents a phase mapping strategy involving discretization in real space. It directly takes :class:`~.MagData` objects and returns :class:`~.PhaseMap` @@ -181,28 +206,23 @@ class PhaseMapperRDRC(PhaseMapper): Attributes ---------- - a : float - The grid spacing in nm. - projector : :class:`~.Projector` - Projector which should be used for the projection of the 3-dimensional magnetization - distribution. - b_0 : float, optional - The magnetic induction corresponding to a magnetization `M`\ :sub:`0` in T. - The default is 1. + kernel : :class:`~pyramid.Kernel` + Convolution kernel, representing the phase contribution of one single magnetized pixel. threshold : float, optional Threshold determining for which voxels the phase contribution will be calculated. The default is 0, which means that all voxels with non-zero magnetization will contribute. Should be above noise level. - geometry : {'disc', 'slab'}, optional - Elementary geometry which is used for the phase contribution of one pixel. - Default is 'disc'. numcore : boolean, optional Boolean choosing if Cython enhanced routines from the :mod:`~.pyramid.numcore` module should be used. Default is True. + m: int + Size of the image space. + n: int + Size of the input space. - ''' + """ - _log = logging.getLogger(__name__+'.PhaseMapperRDRC') + _log = logging.getLogger(__name__ + '.PhaseMapperRDRC') def __init__(self, kernel, threshold=0, numcore=True): self._log.debug('Calling __init__') @@ -211,17 +231,17 @@ class PhaseMapperRDRC(PhaseMapper): self.numcore = numcore self.m = np.prod(kernel.dim_uv) self.n = 2 * self.m - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) def __repr__(self): self._log.debug('Calling __repr__') return '%s(kernel=%r, threshold=%r, numcore=%r)' % \ - (self.__class__, self.kernel, self.threshold, self.numcore) + (self.__class__, self.kernel, self.threshold, self.numcore) def __str__(self): self._log.debug('Calling __str__') return 'PhaseMapperRDRC(kernel=%s, threshold=%s, numcore=%s)' % \ - (self.kernel, self.threshold, self.numcore) + (self.kernel, self.threshold, self.numcore) def __call__(self, mag_data): self._log.debug('Calling __call__') @@ -243,19 +263,19 @@ class PhaseMapperRDRC(PhaseMapper): else: for j in range(dim_uv[0]): for i in range(dim_uv[1]): - u_phase = u_phi[dim_uv[0]-1-j:(2*dim_uv[0]-1)-j, - dim_uv[1]-1-i:(2*dim_uv[1]-1)-i] + u_phase = u_phi[dim_uv[0] - 1 - j:(2 * dim_uv[0] - 1) - j, + dim_uv[1] - 1 - i:(2 * dim_uv[1] - 1) - i] if abs(u_mag[j, i]) > self.threshold: phase += u_mag[j, i] * u_phase - v_phase = v_phi[dim_uv[0]-1-j:(2*dim_uv[0]-1)-j, - dim_uv[1]-1-i:(2*dim_uv[1]-1)-i] + v_phase = v_phi[dim_uv[0] - 1 - j:(2 * dim_uv[0] - 1) - j, + dim_uv[1] - 1 - i:(2 * dim_uv[1] - 1) - i] if abs(v_mag[j, i]) > self.threshold: phase -= v_mag[j, i] * v_phase # Return the phase: return PhaseMap(mag_data.a, phase) def jac_dot(self, vector): - '''Calculate the product of the Jacobi matrix with a given `vector`. + """Calculate the product of the Jacobi matrix with a given `vector`. Parameters ---------- @@ -269,7 +289,7 @@ class PhaseMapperRDRC(PhaseMapper): result : :class:`~numpy.ndarray` (N=1) Product of the Jacobi matrix (which is not explicitely calculated) with the vector. - ''' + """ assert len(vector) == self.n, \ 'vector size not compatible! vector: {}, size: {}'.format(len(vector), self.n) v_dim, u_dim = self.kernel.dim_uv @@ -282,17 +302,17 @@ class PhaseMapperRDRC(PhaseMapper): # Iterate over all contributing pixels (numbered consecutively) for s in range(self.m): # column-wise (two columns at a time, u- and v-component) i = s % u_dim # u-coordinate of current contributing pixel - j = int(s/u_dim) # v-coordinate of current ccontributing pixel - u_min = (u_dim-1) - i # u_dim-1: center of the kernel - u_max = (2*u_dim-1) - i # = u_min + u_dim - v_min = (v_dim-1) - j # v_dim-1: center of the kernel - v_max = (2*v_dim-1) - j # = v_min + v_dim + j = int(s / u_dim) # v-coordinate of current ccontributing pixel + u_min = (u_dim - 1) - i # u_dim-1: center of the kernel + u_max = (2 * u_dim - 1) - i # = u_min + u_dim + v_min = (v_dim - 1) - j # v_dim-1: center of the kernel + v_max = (2 * v_dim - 1) - j # = v_min + v_dim result += vector[s] * self.kernel.u[v_min:v_max, u_min:u_max].reshape(-1) - result -= vector[s+self.m] * self.kernel.v[v_min:v_max, u_min:u_max].reshape(-1) + result -= vector[s + self.m] * self.kernel.v[v_min:v_max, u_min:u_max].reshape(-1) return result def jac_T_dot(self, vector): - '''Calculate the product of the transposed Jacobi matrix with a given `vector`. + """Calculate the product of the transposed Jacobi matrix with a given `vector`. Parameters ---------- @@ -306,7 +326,7 @@ class PhaseMapperRDRC(PhaseMapper): Product of the transposed Jacobi matrix (which is not explicitely calculated) with the vector, which has ``2*N**2`` entries like a 2D magnetic projection. - ''' + """ assert len(vector) == self.m, \ 'vector size not compatible! vector: {}, size: {}'.format(len(vector), self.m) v_dim, u_dim = self.kernel.dim_uv @@ -319,19 +339,19 @@ class PhaseMapperRDRC(PhaseMapper): # Iterate over all contributing pixels (numbered consecutively): for s in range(self.m): # row-wise (two rows at a time, u- and v-component) i = s % u_dim # u-coordinate of current contributing pixel - j = int(s/u_dim) # v-coordinate of current contributing pixel - u_min = (u_dim-1) - i # u_dim-1: center of the kernel - u_max = (2*u_dim-1) - i # = u_min + u_dim - v_min = (v_dim-1) - j # v_dim-1: center of the kernel - v_max = (2*v_dim-1) - j # = v_min + v_dim - result[s] = np.sum(vector*self.u[v_min:v_max, u_min:u_max].reshape(-1)) - result[s+self.m] = np.sum(vector*-self.v[v_min:v_max, u_min:u_max].reshape(-1)) + j = int(s / u_dim) # v-coordinate of current contributing pixel + u_min = (u_dim - 1) - i # u_dim-1: center of the kernel + u_max = (2 * u_dim - 1) - i # = u_min + u_dim + v_min = (v_dim - 1) - j # v_dim-1: center of the kernel + v_max = (2 * v_dim - 1) - j # = v_min + v_dim + result[s] = np.sum(vector * self.kernel.u[v_min:v_max, u_min:u_max].reshape(-1)) + result[s + self.m] = np.sum(vector * + -self.kernel.v[v_min:v_max, u_min:u_max].reshape(-1)) return result class PhaseMapperFDFC(PhaseMapper): - - '''Class representing a phase mapping strategy using a discretization in Fourier space. + """Class representing a phase mapping strategy using a discretization in Fourier space. The :class:`~.PMFourier` class represents a phase mapping strategy involving discretization in Fourier space. It utilizes the Fourier transforms, which are inherently calculated in the @@ -342,19 +362,22 @@ class PhaseMapperFDFC(PhaseMapper): ---------- a : float The grid spacing in nm. - projector : :class:`~.Projector` - Projector which should be used for the projection of the 3-dimensional magnetization - distribution. + dim_uv : tuple of int (N=2) + Dimensions of the 2-dimensional projected magnetization grid for the kernel setup. b_0 : float, optional The magnetic induction corresponding to a magnetization `M`\ :sub:`0` in T. The default is 1. padding : int, optional Factor for the zero padding. The default is 0 (no padding). For a factor of n the number of pixels is increase by ``(1+n)**2``. Padded zeros are cropped at the end. + m: int + Size of the image space. + n: int + Size of the input space. - ''' + """ - _log = logging.getLogger(__name__+'.PhaseMapperFDFC') + _log = logging.getLogger(__name__ + '.PhaseMapperFDFC') def __init__(self, a, dim_uv, b_0=1, padding=0): self._log.debug('Calling __init__') @@ -364,17 +387,17 @@ class PhaseMapperFDFC(PhaseMapper): self.padding = padding self.m = np.prod(dim_uv) self.n = 2 * self.m - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) def __repr__(self): self._log.debug('Calling __repr__') return '%s(a=%r, dim_uv=%r, b_0=%r, padding=%r)' % \ - (self.__class__, self.a, self.dim_uv, self.b_0, self.padding) + (self.__class__, self.a, self.dim_uv, self.b_0, self.padding) def __str__(self): self._log.debug('Calling __str__') return 'PhaseMapperFDFC(a=%s, dim_uv=%s, b_0=%s, padding=%s)' % \ - (self.a, self.dim_uv, self.b_0, self.padding) + (self.a, self.dim_uv, self.b_0, self.padding) def __call__(self, mag_data): self._log.debug('Calling __call__') @@ -385,8 +408,8 @@ class PhaseMapperFDFC(PhaseMapper): v_dim, u_dim = self.dim_uv u_mag, v_mag = mag_data.magnitude[0:2, 0, ...] # Create zero padded matrices: - u_pad = int(u_dim/2 * self.padding) - v_pad = int(v_dim/2 * self.padding) + u_pad = int(u_dim / 2 * self.padding) + v_pad = int(v_dim / 2 * self.padding) u_mag_pad = np.pad(u_mag, ((v_pad, v_pad), (u_pad, u_pad)), 'constant') v_mag_pad = np.pad(v_mag, ((v_pad, v_pad), (u_pad, u_pad)), 'constant') # Fourier transform of the two components: @@ -397,16 +420,15 @@ class PhaseMapperFDFC(PhaseMapper): f_u = np.linspace(0, f_nyq, u_mag_fft.shape[1]) f_v = np.linspace(-f_nyq, f_nyq, u_mag_fft.shape[0], endpoint=False) f_uu, f_vv = np.meshgrid(f_u, f_v) - coeff = - (1j*self.b_0*self.a) / (2*PHI_0) # Minus because of negative z-direction - phase_fft = coeff * (u_mag_fft*f_vv - v_mag_fft*f_uu) / (f_uu**2 + f_vv**2 + 1e-30) + coeff = - (1j * self.b_0 * self.a) / (2 * PHI_0) # Minus because of negative z-direction + phase_fft = coeff * (u_mag_fft * f_vv - v_mag_fft * f_uu) / (f_uu ** 2 + f_vv ** 2 + 1e-30) # Transform to real space and revert padding: phase_pad = np.fft.irfft2(np.fft.ifftshift(phase_fft, axes=0)) - phase = phase_pad[v_pad:v_pad+v_dim, u_pad:u_pad+u_dim] + phase = phase_pad[v_pad:v_pad + v_dim, u_pad:u_pad + u_dim] return PhaseMap(mag_data.a, phase) def jac_dot(self, vector): - self._log.debug('Calling jac_dot') - '''Calculate the product of the Jacobi matrix with a given `vector`. + """Calculate the product of the Jacobi matrix with a given `vector`. Parameters ---------- @@ -420,23 +442,38 @@ class PhaseMapperFDFC(PhaseMapper): result : :class:`~numpy.ndarray` (N=1) Product of the Jacobi matrix (which is not explicitely calculated) with the vector. - ''' + """ + self._log.debug('Calling jac_dot') assert len(vector) == self.n, \ 'vector size not compatible! vector: {}, size: {}'.format(len(vector), self.n) - mag_proj = MagData(self.a, np.zeros((3, 1)+self.dim_uv, dtype=np.float32)) - magnitude_proj = np.reshape(vector, (2,)+self.dim_uv) + mag_proj = MagData(self.a, np.zeros((3, 1) + self.dim_uv, dtype=np.float32)) + magnitude_proj = np.reshape(vector, (2,) + self.dim_uv) mag_proj.magnitude[:2, 0, ...] = magnitude_proj return self(mag_proj).phase_vec def jac_T_dot(self, vector): - raise NotImplementedError() + """Calculate the product of the transposed Jacobi matrix with a given `vector`. + + Parameters + ---------- + vector : :class:`~numpy.ndarray` (N=1) + Vector with ``N**2`` entries which represents a matrix with dimensions like a scalar + phasemap. + + Returns + ------- + result : :class:`~numpy.ndarray` (N=1) + Product of the transposed Jacobi matrix (which is not explicitely calculated) with + the vector, which has ``2*N**2`` entries like a 2D magnetic projection. + """ + raise NotImplementedError() -class PhaseMapperElectric(PhaseMapper): - '''Class representing a phase mapping strategy for the electrostatic contribution. +class PhaseMapperMIP(PhaseMapper): + """Class representing a phase mapping strategy for the electrostatic contribution. - The :class:`~.PMElectric` class represents a phase mapping strategy for the electrostatic + The :class:`~.PhaseMapperMIP` class represents a phase mapping strategy for the electrostatic contribution to the electron phase shift which results e.g. from the mean inner potential in certain samples and which is sensitive to properties of the electron microscope. It directly takes :class:`~.MagData` objects and returns :class:`~.PhaseMap` objects. @@ -445,9 +482,8 @@ class PhaseMapperElectric(PhaseMapper): ---------- a : float The grid spacing in nm. - projector : :class:`~.Projector` - Projector which should be used for the projection of the 3-dimensional magnetization - distribution. + dim_uv : tuple of int (N=2) + Dimensions of the 2-dimensional projected magnetization grid for the kernel setup. v_0 : float, optional The mean inner potential of the specimen in V. The default is 1. v_acc : float, optional @@ -455,10 +491,14 @@ class PhaseMapperElectric(PhaseMapper): threshold : float, optional Threshold for the recognition of the specimen location. The default is 0, which means that all voxels with non-zero magnetization will contribute. Should be above noise level. + m: int + Size of the image space. + n: int + Size of the input space. - ''' + """ - _log = logging.getLogger(__name__+'.PhaseMapperElectric') + _log = logging.getLogger(__name__ + '.PhaseMapperMIP') def __init__(self, a, dim_uv, v_0=1, v_acc=30000, threshold=0): self._log.debug('Calling __init__') @@ -470,46 +510,77 @@ class PhaseMapperElectric(PhaseMapper): self.m = np.prod(self.dim_uv) self.n = np.prod(self.dim_uv) # Coefficient calculation: - lam = H_BAR / np.sqrt(2 * M_E * Q_E * v_acc * (1 + Q_E*v_acc / (2*M_E*C**2))) - C_e = 2*pi*Q_E/lam * (Q_E*v_acc + M_E*C**2) / (Q_E*v_acc * (Q_E*v_acc + 2*M_E*C**2)) + lam = H_BAR / np.sqrt(2 * M_E * Q_E * v_acc * (1 + Q_E * v_acc / (2 * M_E * C ** 2))) + C_e = 2 * pi * Q_E / lam * (Q_E * v_acc + M_E * C ** 2) / ( + Q_E * v_acc * (Q_E * v_acc + 2 * M_E * C ** 2)) self.coeff = v_0 * C_e * a * 1E-9 - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) def __repr__(self): self._log.debug('Calling __repr__') return '%s(a=%r, dim_uv=%r, v_0=%r, v_acc=%r, threshold=%r)' % \ - (self.__class__, self.a, self.dim_uv, self.v_0, self.v_acc, self.threshold) + (self.__class__, self.a, self.dim_uv, self.v_0, self.v_acc, self.threshold) def __str__(self): self._log.debug('Calling __str__') - return 'PhaseMapperElectric(a=%s, dim_uv=%s, v_0=%s, v_acc=%s, threshold=%s)' % \ - (self.a, self.dim_uv, self.v_0, self.v_acc, self.threshold) + return 'PhaseMapperMIP(a=%s, dim_uv=%s, v_0=%s, v_acc=%s, threshold=%s)' % \ + (self.a, self.dim_uv, self.v_0, self.v_acc, self.threshold) def __call__(self, mag_data): - raise NotImplementedError() # TODO: Implement right! self._log.debug('Calling __call__') - assert isinstance(mag_data, MagData), 'Only MagData objects can be mapped!' - assert mag_data.a == self.a, 'Grid spacing has to match!' - assert mag_data.dim[0] == 1, 'Magnetic distribution must be 2-dimensional!' - assert mag_data.dim[1:3] == self.dim_uv, 'Dimensions do not match!' - return self.coeff * mag_data.get_mask(self.threshold)[0, ...].reshape(self.dim_uv) - # Calculate mask: - mask = mag_data.get_mask(self.threshold) - # Project and calculate phase: - # TODO: check if projector manages scalar multiplication (problem with MagData) and fix! - projection = self.projector(mask.reshape(-1)).reshape(self.projector.dim_uv) - phase = self.coeff * projection - return PhaseMap(mag_data.a, phase) + raise NotImplementedError() # TODO: Implement right! + # assert isinstance(mag_data, MagData), 'Only MagData objects can be mapped!' + # assert mag_data.a == self.a, 'Grid spacing has to match!' + # assert mag_data.dim[0] == 1, 'Magnetic distribution must be 2-dimensional!' + # assert mag_data.dim[1:3] == self.dim_uv, 'Dimensions do not match!' + # return self.coeff * mag_data.get_mask(self.threshold)[0, ...].reshape(self.dim_uv) + # # Calculate mask: + # mask = mag_data.get_mask(self.threshold) + # # Project and calculate phase: + # # TODO: check if projector manages scalar multiplication (problem with MagData) and fix! + # projection = self.projector(mask.reshape(-1)).reshape(self.projector.dim_uv) + # phase = self.coeff * projection + # return PhaseMap(mag_data.a, phase) def jac_dot(self, vector): + """Calculate the product of the Jacobi matrix with a given `vector`. + + Parameters + ---------- + vector : :class:`~numpy.ndarray` (N=1) + Vectorized form of the magnetization in `u`- and `v`-direction of every pixel + (row-wise). The first ``N**2`` elements have to correspond to the `u`-, the next + ``N**2`` elements to the `v`-component of the magnetization. + + Returns + ------- + result : :class:`~numpy.ndarray` (N=1) + Product of the Jacobi matrix (which is not explicitely calculated) with the vector. + + """ raise NotImplementedError() def jac_T_dot(self, vector): + """Calculate the product of the transposed Jacobi matrix with a given `vector`. + + Parameters + ---------- + vector : :class:`~numpy.ndarray` (N=1) + Vector with ``N**2`` entries which represents a matrix with dimensions like a scalar + phasemap. + + Returns + ------- + result : :class:`~numpy.ndarray` (N=1) + Product of the transposed Jacobi matrix (which is not explicitely calculated) with + the vector, which has ``2*N**2`` entries like a 2D magnetic projection. + + """ raise NotImplementedError() def pm(mag_data, axis='z', dim_uv=None, b_0=1): - '''Convenience function for fast phase mapping. + """Convenience function for fast phase mapping. Parameters ---------- @@ -524,14 +595,14 @@ def pm(mag_data, axis='z', dim_uv=None, b_0=1): Saturation magnetization in Tesla, which is used for the phase calculation. Default is 1. Returns ------- - mag_data : :class:`~pyramid.magdata.MagData` - The reconstructed magnetic distribution as a :class:`~.MagData` object. + phase_map : :class:`~pyramid.phasemap.PhaseMap` + The calculated phase map as a :class:`~.PhaseMap` object. - ''' + """ _log.debug('Calling pm') projector = SimpleProjector(mag_data.dim, axis=axis, dim_uv=dim_uv) mag_proj = projector(mag_data) - phasemapper = PhaseMapperRDFC(Kernel(mag_data.a, projector.dim_uv)) + phasemapper = PhaseMapperRDFC(Kernel(mag_data.a, projector.dim_uv, b_0=b_0)) phase_map = phasemapper(mag_proj) phase_map.mask = mag_proj.get_mask()[0, ...] return phase_map diff --git a/pyramid/projector.py b/pyramid/projector.py index 937fc0a..5f0e238 100644 --- a/pyramid/projector.py +++ b/pyramid/projector.py @@ -5,28 +5,25 @@ """This module provides the abstract base class :class:`~.Projector` and concrete subclasses for projections of vector and scalar fields.""" - from __future__ import division +import abc +import itertools +import logging + import numpy as np from numpy import pi -import itertools from scipy.sparse import coo_matrix, csr_matrix -import abc +import pyramid.fft as fft from pyramid.magdata import MagData from pyramid.quaternion import Quaternion -import pyramid.fft as fft - -import logging - __all__ = ['RotTiltProjector', 'XTiltProjector', 'YTiltProjector', 'SimpleProjector'] class Projector(object): - - '''Abstract base class representing a projection function. + """Abstract base class representing a projection function. The :class:`~.Projector` class represents a projection function for a 3-dimensional vector- or scalar field onto a 2-dimensional grid. :class:`~.Projector` is an abstract base @@ -57,10 +54,10 @@ class Projector(object): n: int Size of the input space. - ''' + """ __metaclass__ = abc.ABCMeta - _log = logging.getLogger(__name__+'.Projector') + _log = logging.getLogger(__name__ + '.Projector') @abc.abstractmethod def __init__(self, dim, dim_uv, weight, coeff): @@ -72,32 +69,32 @@ class Projector(object): self.size_2d, self.size_3d = weight.shape self.n = 3 * np.prod(dim) self.m = 2 * np.prod(dim_uv) - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) def __repr__(self): self._log.debug('Calling __repr__') return '%s(dim=%r, dim_uv=%r, weight=%r, coeff=%r)' % \ - (self.__class__, self.dim, self.dim_uv, self.weight, self.coeff) + (self.__class__, self.dim, self.dim_uv, self.weight, self.coeff) def __str__(self): self._log.debug('Calling __str__') return 'Projector(dim=%s, dim_uv=%s, coeff=%s)' % (self.dim, self.dim_uv, self.coeff) def __call__(self, mag_data): - mag_proj = MagData(mag_data.a, fft.zeros((3, 1)+self.dim_uv, dtype=fft.FLOAT)) - magnitude_proj = self.jac_dot(mag_data.mag_vec).reshape((2, )+self.dim_uv) + mag_proj = MagData(mag_data.a, fft.zeros((3, 1) + self.dim_uv, dtype=fft.FLOAT)) + magnitude_proj = self.jac_dot(mag_data.mag_vec).reshape((2,) + self.dim_uv) mag_proj.magnitude[0:2, 0, ...] = magnitude_proj return mag_proj def _vector_field_projection(self, vector): - result = fft.zeros(2*self.size_2d, dtype=fft.FLOAT) + result = fft.zeros(2 * self.size_2d, dtype=fft.FLOAT) # Go over all possible component projections (z, y, x) to (u, v): vec_x, vec_y, vec_z = np.split(vector, 3) vec_x_weighted = self.weight.dot(vec_x) vec_y_weighted = self.weight.dot(vec_y) vec_z_weighted = self.weight.dot(vec_z) slice_u = slice(0, self.size_2d) - slice_v = slice(self.size_2d, 2*self.size_2d) + slice_v = slice(self.size_2d, 2 * self.size_2d) if self.coeff[0][0] != 0: # x to u result[slice_u] += self.coeff[0][0] * vec_x_weighted if self.coeff[0][1] != 0: # y to u @@ -113,14 +110,14 @@ class Projector(object): return result def _vector_field_projection_T(self, vector): - result = np.zeros(3*self.size_3d, dtype=fft.FLOAT) + result = np.zeros(3 * self.size_3d, dtype=fft.FLOAT) # Go over all possible component projections (u, v) to (z, y, x): vec_u, vec_v = np.split(vector, 2) vec_u_weighted = self.weight.T.dot(vec_u) vec_v_weighted = self.weight.T.dot(vec_v) slice_x = slice(0, self.size_3d) - slice_y = slice(self.size_3d, 2*self.size_3d) - slice_z = slice(2*self.size_3d, 3*self.size_3d) + slice_y = slice(self.size_3d, 2 * self.size_3d) + slice_z = slice(2 * self.size_3d, 3 * self.size_3d) if self.coeff[0][0] != 0: # u to x result[slice_x] += self.coeff[0][0] * vec_u_weighted if self.coeff[0][1] != 0: # u to y @@ -144,7 +141,7 @@ class Projector(object): return np.array(self.weight.T.dot(vector)) def jac_dot(self, vector): - '''Multiply a `vector` with the jacobi matrix of this :class:`~.Projector` object. + """Multiply a `vector` with the jacobi matrix of this :class:`~.Projector` object. Parameters ---------- @@ -158,8 +155,8 @@ class Projector(object): Vector containing the projected field of the 2-dimensional grid. The length is always`size_2d`. - ''' - if len(vector) == 3*self.size_3d: # mode == 'vector' + """ + if len(vector) == 3 * self.size_3d: # mode == 'vector' return self._vector_field_projection(vector) elif len(vector) == self.size_3d: # mode == 'scalar' return self._scalar_field_projection(vector) @@ -168,7 +165,7 @@ class Projector(object): 'vector- or scalar-field-projection!') def jac_T_dot(self, vector): - '''Multiply a `vector` with the transp. jacobi matrix of this :class:`~.Projector` object. + """Multiply a `vector` with the transp. jacobi matrix of this :class:`~.Projector` object. Parameters ---------- @@ -182,8 +179,8 @@ class Projector(object): Vector containing the multiplication of the input with the transposed jacobi matrix of the :class:`~.Projector` object. - ''' - if len(vector) == 2*self.size_2d: # mode == 'vector' + """ + if len(vector) == 2 * self.size_2d: # mode == 'vector' return self._vector_field_projection_T(vector) elif len(vector) == self.size_2d: # mode == 'scalar' return self._scalar_field_projection_T(vector) @@ -193,7 +190,7 @@ class Projector(object): @abc.abstractmethod def get_info(self, verbose): - '''Get specific information about the projector as a string. + """Get specific information about the projector as a string. Parameters ---------- @@ -206,13 +203,12 @@ class Projector(object): info : string Information about the projector as a string, e.g. for the use in plot titles. - ''' + """ raise NotImplementedError() class RotTiltProjector(Projector): - - '''Class representing a projection function with a rotation around z followed by tilt around x. + """Class representing a projection function with a rotation around z followed by tilt around x. The :class:`~.XTiltProjector` class represents a projection function for a 3-dimensional vector- or scalar field onto a 2-dimensional grid, which is a concrete subclass of @@ -235,9 +231,9 @@ class RotTiltProjector(Projector): sparsity : float Measures the sparsity of the weighting (not the complete one!), 1 means completely sparse! - ''' + """ - _log = logging.getLogger(__name__+'.RotTiltProjector') + _log = logging.getLogger(__name__ + '.RotTiltProjector') def __init__(self, dim, rotation, tilt, dim_uv=None, subcount=11): self._log.debug('Calling __init__') @@ -245,7 +241,7 @@ class RotTiltProjector(Projector): self.tilt = tilt # Determine dimensions: dim_z, dim_y, dim_x = dim - center = (dim_z/2., dim_y/2., dim_x/2.) + center = (dim_z / 2., dim_y / 2., dim_x / 2.) if dim_uv is None: dim_v = max(dim_x, dim_y) # first rotate around z-axis (take x and y into account) dim_u = max(dim_v, dim_z) # then tilt around x-axis (now z matters, too) @@ -254,17 +250,17 @@ class RotTiltProjector(Projector): # Creating coordinate list of all voxels: voxels = list(itertools.product(range(dim_z), range(dim_y), range(dim_x))) # Calculate vectors to voxels relative to rotation center: - voxel_vecs = (np.asarray(voxels)+0.5 - np.asarray(center)).T + voxel_vecs = (np.asarray(voxels) + 0.5 - np.asarray(center)).T # Create tilt, rotation and combined quaternion, careful: Quaternion(w,x,y,z), not (z,y,x): quat_x = Quaternion.from_axisangle((0, 1, 0), tilt) # Tilt around y-axis quat_z = Quaternion.from_axisangle((0, 0, 1), rotation) # Rotate around z-axis quat = quat_x * quat_z # Combined quaternion (first rotate around z, then tilt around x) # Calculate impact positions on the projected pixel coordinate grid (flip because quat.): impacts = np.flipud(quat.matrix[:2, :].dot(np.flipud(voxel_vecs))) # only care for x/y - impacts[1, :] += dim_u/2. # Shift back to normal indices - impacts[0, :] += dim_v/2. # Shift back to normal indices + impacts[1, :] += dim_u / 2. # Shift back to normal indices + impacts[0, :] += dim_v / 2. # Shift back to normal indices # Calculate equivalence radius: - R = (3/(4*np.pi))**(1/3.) + R = (3 / (4 * np.pi)) ** (1 / 3.) # Prepare weight matrix calculation: rows = [] # 2D projection columns = [] # 3D distribution @@ -273,42 +269,43 @@ class RotTiltProjector(Projector): weight_lookup = self._create_weight_lookup(subcount, R) # Go over all voxels: for i, voxel in enumerate(voxels): - column_index = voxel[0]*dim_y*dim_x + voxel[1]*dim_x + voxel[2] + column_index = voxel[0] * dim_y * dim_x + voxel[1] * dim_x + voxel[2] remainder, impact = np.modf(impacts[:, i]) # split index of impact and remainder! sub_pixel = (remainder * subcount).astype(dtype=np.int) # sub_pixel inside impact px. # Go over all influenced pixels (impact and neighbours, indices are [0, 1, 2]!): for px_ind in list(itertools.product(range(3), range(3))): # Pixel indices influenced by the impact (px_ind-1 to center them around impact): - pixel = (impact + np.array(px_ind)-1).astype(dtype=np.int) + pixel = (impact + np.array(px_ind) - 1).astype(dtype=np.int) # Check if pixel is out of bound: if 0 <= pixel[0] < dim_uv[0] and 0 <= pixel[1] < dim_uv[1]: # Lookup weight in 4-dimensional lookup table! weight = weight_lookup[px_ind[0], px_ind[1], sub_pixel[0], sub_pixel[1]] # Only write into sparse matrix if weight is not zero: if weight != 0.: - row_index = pixel[0]*dim_u + pixel[1] + row_index = pixel[0] * dim_u + pixel[1] columns.append(column_index) rows.append(row_index) data.append(weight) # Calculate weight matrix and coefficients for jacobi matrix: shape = (np.prod(dim_uv), np.prod(dim)) - self.sparsity = 1. - len(data)/np.prod(shape, dtype=np.float) + self.sparsity = 1. - len(data) / np.prod(shape, dtype=np.float) weights = csr_matrix(coo_matrix((data, (rows, columns)), shape=shape)) # Calculate coefficients by rotating unity matrix (unit vectors, (x,y,z)): coeff = quat.matrix[:2, :].dot(np.eye(3)) super(RotTiltProjector, self).__init__(dim, dim_uv, weights, coeff) - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) - def _create_weight_lookup(self, subcount, R): + @staticmethod + def _create_weight_lookup(subcount, R): s = subcount Rz = R * s # Radius in subgrid units - dim_zoom = (3*s, 3*s) # Dimensions of the subgrid, (3, 3) because of neighbour count! - cent_zoom = (np.asarray(dim_zoom)/2.).astype(dtype=np.int) # Center of the subgrid + dim_zoom = (3 * s, 3 * s) # Dimensions of the subgrid, (3, 3) because of neighbour count! + cent_zoom = (np.asarray(dim_zoom) / 2.).astype(dtype=np.int) # Center of the subgrid y, x = np.indices(dim_zoom) y -= cent_zoom[0] x -= cent_zoom[1] # Calculate projected thickness of an equivalence sphere (normed!): - d = np.where(np.hypot(x, y) <= Rz, Rz**2-x**2-y**2, 0) + d = np.where(np.hypot(x, y) <= Rz, Rz ** 2 - x ** 2 - y ** 2, 0) d = np.sqrt(d) d /= d.sum() # Create lookup table (4D): @@ -318,18 +315,18 @@ class RotTiltProjector(Projector): pixel_lb = np.array(pixel) * s # Convert to subgrid, hit bottom left of the pixel! # Go over all subpixels in the center that can be hit: for sub_pixel in list(itertools.product(range(s), range(s))): - shift = np.array(sub_pixel) - np.array((s//2, s//2)) # relative to center! + shift = np.array(sub_pixel) - np.array((s // 2, s // 2)) # relative to center! lb = pixel_lb - shift # Shift summing zone according to hit subpixel! # Make sure, that the summing zone is in bounds (otherwise correct accordingly): lb = np.where(lb >= 0, lb, [0, 0]) - tr = np.where(lb < 3*s, lb+np.array((s, s)), [3*s, 3*s]) + tr = np.where(lb < 3 * s, lb + np.array((s, s)), [3 * s, 3 * s]) # Calculate weight by summing over the summing zone: weight = d[lb[0]:tr[0], lb[1]:tr[1]].sum() lookup[pixel[0], pixel[1], sub_pixel[0], sub_pixel[1]] = weight return lookup def get_info(self, verbose=False): - '''Get specific information about the projector as a string. + """Get specific information about the projector as a string. Parameters ---------- @@ -342,9 +339,9 @@ class RotTiltProjector(Projector): info : string Information about the projector as a string, e.g. for the use in plot titles. - ''' - theta_ang = int(np.round(self.rotation*180/pi)) - phi_ang = int(np.round(self.tilt*180/pi)) + """ + theta_ang = int(np.round(self.rotation * 180 / pi)) + phi_ang = int(np.round(self.tilt * 180 / pi)) if verbose: return u'$\\theta = {:d}$°, $\phi = {:d}$°'.format(theta_ang, phi_ang) else: @@ -352,8 +349,7 @@ class RotTiltProjector(Projector): class XTiltProjector(Projector): - - '''Class representing a projection function with a tilt around the x-axis. + """Class representing a projection function with a tilt around the x-axis. The :class:`~.XTiltProjector` class represents a projection function for a 3-dimensional vector- or scalar field onto a 2-dimensional grid, which is a concrete subclass of @@ -368,37 +364,11 @@ class XTiltProjector(Projector): dim_uv : tuple (N=2), optional Dimensions (v, u) of the projection. If not set defaults to the (y, x)-dimensions. - ''' + """ - _log = logging.getLogger(__name__+'.XTiltProjector') + _log = logging.getLogger(__name__ + '.XTiltProjector') def __init__(self, dim, tilt, dim_uv=None): - - def get_position(points, center, tilt, size): - point_vecs = np.asarray(points)+0.5 - np.asarray(center) # vectors pointing to points - direc_vec = np.array((np.cos(tilt), -np.sin(tilt))) # vector pointing along projection - distances = -np.cross(point_vecs, direc_vec) # here (special case): divisor is one! - # minus because sign is derived of -sin(angle(point_vec, direc_vec)) neg between 0-180° - return distances + size/2. # Shift to the center of the projection - - def get_impact(pos, r, size): - return [x for x in np.arange(np.floor(pos-r), np.floor(pos+r)+1, dtype=int) - if 0 <= x < size] - - def get_weight(delta, rho): # use circles to represent the voxels - lo, up = delta-rho, delta+rho - # Upper boundary: - if up >= 1: - w_up = 0.5 - else: - w_up = (up*np.sqrt(1-up**2) + np.arctan(up/np.sqrt(1-up**2))) / pi - # Lower boundary: - if lo <= -1: - w_lo = -0.5 - else: - w_lo = (lo*np.sqrt(1-lo**2) + np.arctan(lo/np.sqrt(1-lo**2))) / pi - return w_up - w_lo - self._log.debug('Calling __init__') self.tilt = tilt # Set starting variables: @@ -411,41 +381,71 @@ class XTiltProjector(Projector): # Creating coordinate list of all voxels: voxels = list(itertools.product(range(dim_proj), range(dim_perp))) # z-y-plane # Calculate positions along the projected pixel coordinate system: - center = (dim_proj/2., dim_perp/2.) - positions = get_position(voxels, center, tilt, dim_v) + center = (dim_proj / 2., dim_perp / 2.) + positions = self._get_position(voxels, center, tilt, dim_v) # Calculate weight-matrix: - r = 1/np.sqrt(np.pi) # radius of the voxel circle + r = 1 / np.sqrt(np.pi) # radius of the voxel circle rho = 0.5 / r row = [] col = [] data = [] # one slice: for i, voxel in enumerate(voxels): - impacts = get_impact(positions[i], r, dim_v) # impact along projected y-axis - voxel_index = voxel[0]*dim_rot*dim_perp + voxel[1]*dim_rot # 0: z, 1: y + impacts = self._get_impact(positions[i], r, dim_v) # impact along projected y-axis + voxel_index = voxel[0] * dim_rot * dim_perp + voxel[1] * dim_rot # 0: z, 1: y for impact in impacts: - impact_index = impact*dim_u+int((dim_u-dim_rot)/2) - distance = np.abs(impact+0.5 - positions[i]) + impact_index = impact * dim_u + int((dim_u - dim_rot) / 2) + distance = np.abs(impact + 0.5 - positions[i]) delta = distance / r col.append(voxel_index) row.append(impact_index) - data.append(get_weight(delta, rho)) + data.append(self._get_weight(delta, rho)) # All other slices (along x): columns = col rows = row for s in np.arange(1, dim_rot): - columns = np.hstack((np.array(columns), np.array(col)+s)) - rows = np.hstack((np.array(rows), np.array(row)+s)) + columns = np.hstack((np.array(columns), np.array(col) + s)) + rows = np.hstack((np.array(rows), np.array(row) + s)) # Calculate weight matrix and coefficients for jacobi matrix: shape = (np.prod(dim_uv), np.prod(dim)) - self.sparsity = 1. - len(data)/np.prod(shape, dtype=np.float) + self.sparsity = 1. - len(data) / np.prod(shape, dtype=np.float) weight = csr_matrix(coo_matrix((np.tile(data, dim_rot), (rows, columns)), shape=shape)) coeff = [[1, 0, 0], [0, np.cos(tilt), np.sin(tilt)]] super(XTiltProjector, self).__init__(dim, dim_uv, weight, coeff) - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) + + @staticmethod + def _get_position(points, center, tilt, size): + point_vecs = np.asarray(points) + 0.5 - np.asarray( + center) # vectors pointing to points + direc_vec = np.array((np.cos(tilt), -np.sin(tilt))) # vector pointing along projection + distances = -np.cross(point_vecs, direc_vec) # here (special case): divisor is one! + # minus because sign is derived of -sin(angle(point_vec, direc_vec)) neg between 0-180° + distances += size / 2. # Shift to the center of the projection + return distances + + @staticmethod + def _get_impact(pos, r, size): + return [x for x in np.arange(np.floor(pos - r), np.floor(pos + r) + 1, dtype=int) + if 0 <= x < size] + + @staticmethod + def _get_weight(delta, rho): # use circles to represent the voxels + lo, up = delta - rho, delta + rho + # Upper boundary: + if up >= 1: + w_up = 0.5 + else: + w_up = (up * np.sqrt(1 - up ** 2) + np.arctan(up / np.sqrt(1 - up ** 2))) / pi + # Lower boundary: + if lo <= -1: + w_lo = -0.5 + else: + w_lo = (lo * np.sqrt(1 - lo ** 2) + np.arctan(lo / np.sqrt(1 - lo ** 2))) / pi + return w_up - w_lo def get_info(self, verbose=False): - '''Get specific information about the projector as a string. + """Get specific information about the projector as a string. Parameters ---------- @@ -458,16 +458,15 @@ class XTiltProjector(Projector): info : string Information about the projector as a string, e.g. for the use in plot titles. - ''' + """ if verbose: - return u'x-tilt: $\phi = {:d}$°'.format(int(np.round(self.tilt*180/pi))) + return u'x-tilt: $\phi = {:d}$°'.format(int(np.round(self.tilt * 180 / pi))) else: - return u'xtilt_phi={:d}°'.format(int(np.round(self.tilt*180/pi))) + return u'xtilt_phi={:d}°'.format(int(np.round(self.tilt * 180 / pi))) class YTiltProjector(Projector): - - '''Class representing a projection function with a tilt around the y-axis. + """Class representing a projection function with a tilt around the y-axis. The :class:`~.YTiltProjector` class represents a projection function for a 3-dimensional vector- or scalar field onto a 2-dimensional grid, which is a concrete subclass of @@ -482,37 +481,11 @@ class YTiltProjector(Projector): dim_uv : tuple (N=2), optional Dimensions (v, u) of the projection. If not set defaults to the (y, x)-dimensions. - ''' + """ - _log = logging.getLogger(__name__+'.YTiltProjector') + _log = logging.getLogger(__name__ + '.YTiltProjector') def __init__(self, dim, tilt, dim_uv=None): - - def get_position(points, center, tilt, size): - point_vecs = np.asarray(points)+0.5 - np.asarray(center) # vectors pointing to points - direc_vec = np.array((np.cos(tilt), -np.sin(tilt))) # vector pointing along projection - distances = -np.cross(point_vecs, direc_vec) # here (special case): divisor is one! - # minus because sign is derived of -sin(angle(point_vec, direc_vec)) neg between 0-180° - return distances + size/2. # Shift to the center of the projection - - def get_impact(pos, r, size): - return [x for x in np.arange(np.floor(pos-r), np.floor(pos+r)+1, dtype=int) - if 0 <= x < size] - - def get_weight(delta, rho): # use circles to represent the voxels - lo, up = delta-rho, delta+rho - # Upper boundary: - if up >= 1: - w_up = 0.5 - else: - w_up = (up*np.sqrt(1-up**2) + np.arctan(up/np.sqrt(1-up**2))) / pi - # Lower boundary: - if lo <= -1: - w_lo = -0.5 - else: - w_lo = (lo*np.sqrt(1-lo**2) + np.arctan(lo/np.sqrt(1-lo**2))) / pi - return w_up - w_lo - self._log.debug('Calling __init__') self.tilt = tilt # Set starting variables: @@ -525,41 +498,71 @@ class YTiltProjector(Projector): # Creating coordinate list of all voxels: voxels = list(itertools.product(range(dim_proj), range(dim_perp))) # z-x-plane # Calculate positions along the projected pixel coordinate system: - center = (dim_proj/2., dim_perp/2.) - positions = get_position(voxels, center, tilt, dim_u) + center = (dim_proj / 2., dim_perp / 2.) + positions = self._get_position(voxels, center, tilt, dim_u) # Calculate weight-matrix: - r = 1/np.sqrt(np.pi) # radius of the voxel circle + r = 1 / np.sqrt(np.pi) # radius of the voxel circle rho = 0.5 / r row = [] col = [] data = [] # one slice: for i, voxel in enumerate(voxels): - impacts = get_impact(positions[i], r, dim_u) # impact along projected x-axis - voxel_index = voxel[0]*dim_perp*dim_rot + voxel[1] # 0: z, 1: x + impacts = self._get_impact(positions[i], r, dim_u) # impact along projected x-axis + voxel_index = voxel[0] * dim_perp * dim_rot + voxel[1] # 0: z, 1: x for impact in impacts: - impact_index = impact+int((dim_v-dim_rot)/2)*dim_u - distance = np.abs(impact+0.5 - positions[i]) + impact_index = impact + int((dim_v - dim_rot) / 2) * dim_u + distance = np.abs(impact + 0.5 - positions[i]) delta = distance / r col.append(voxel_index) row.append(impact_index) - data.append(get_weight(delta, rho)) + data.append(self._get_weight(delta, rho)) # All other slices (along y): columns = col rows = row for s in np.arange(1, dim_rot): - columns = np.hstack((np.array(columns), np.array(col)+s*dim_perp)) - rows = np.hstack((np.array(rows), np.array(row)+s*dim_u)) + columns = np.hstack((np.array(columns), np.array(col) + s * dim_perp)) + rows = np.hstack((np.array(rows), np.array(row) + s * dim_u)) # Calculate weight matrix and coefficients for jacobi matrix: shape = (np.prod(dim_uv), np.prod(dim)) - self.sparsity = 1. - len(data)/np.prod(shape, dtype=np.float) + self.sparsity = 1. - len(data) / np.prod(shape, dtype=np.float) weight = csr_matrix(coo_matrix((np.tile(data, dim_rot), (rows, columns)), shape=shape)) coeff = [[np.cos(tilt), 0, np.sin(tilt)], [0, 1, 0]] super(YTiltProjector, self).__init__(dim, dim_uv, weight, coeff) - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) + + @staticmethod + def _get_position(points, center, tilt, size): + point_vecs = np.asarray(points) + 0.5 - np.asarray( + center) # vectors pointing to points + direc_vec = np.array((np.cos(tilt), -np.sin(tilt))) # vector pointing along projection + distances = -np.cross(point_vecs, direc_vec) # here (special case): divisor is one! + # minus because sign is derived of -sin(angle(point_vec, direc_vec)) neg between 0-180° + distances += size / 2. # Shift to the center of the projection + return distances + + @staticmethod + def _get_impact(pos, r, size): + return [x for x in np.arange(np.floor(pos - r), np.floor(pos + r) + 1, dtype=int) + if 0 <= x < size] + + @staticmethod + def _get_weight(delta, rho): # use circles to represent the voxels + lo, up = delta - rho, delta + rho + # Upper boundary: + if up >= 1: + w_up = 0.5 + else: + w_up = (up * np.sqrt(1 - up ** 2) + np.arctan(up / np.sqrt(1 - up ** 2))) / pi + # Lower boundary: + if lo <= -1: + w_lo = -0.5 + else: + w_lo = (lo * np.sqrt(1 - lo ** 2) + np.arctan(lo / np.sqrt(1 - lo ** 2))) / pi + return w_up - w_lo def get_info(self, verbose=False): - '''Get specific information about the projector as a string. + """Get specific information about the projector as a string. Parameters ---------- @@ -572,16 +575,15 @@ class YTiltProjector(Projector): info : string Information about the projector as a string, e.g. for the use in plot titles. - ''' + """ if verbose: - return u'y-tilt: $\phi = {:d}$°'.format(int(np.round(self.tilt*180/pi))) + return u'y-tilt: $\phi = {:d}$°'.format(int(np.round(self.tilt * 180 / pi))) else: - return u'ytilt_phi={:d}°'.format(int(np.round(self.tilt*180/pi))) + return u'ytilt_phi={:d}°'.format(int(np.round(self.tilt * 180 / pi))) class SimpleProjector(Projector): - - '''Class representing a projection function along one of the major axes. + """Class representing a projection function along one of the major axes. The :class:`~.SimpleProjector` class represents a projection function for a 3-dimensional vector- or scalar field onto a 2-dimensional grid, which is a concrete subclass of @@ -597,10 +599,11 @@ class SimpleProjector(Projector): dim_uv : tuple (N=2), optional Dimensions (v, u) of the projection. If not set it uses the 3D default dimensions. - ''' + """ - _log = logging.getLogger(__name__+'.SimpleProjector') + _log = logging.getLogger(__name__ + '.SimpleProjector') AXIS_DICT = {'z': (0, 1, 2), 'y': (1, 0, 2), 'x': (2, 1, 0)} # (0:z, 1:y, 2:x) -> (proj, v, u) + # coordinate switch for 'x': u, v --> z, y (not y, z!)! def __init__(self, dim, axis='z', dim_uv=None): @@ -613,7 +616,7 @@ class SimpleProjector(Projector): size_2d = dim_u * dim_v size_3d = np.prod(dim) data = np.repeat(1, size_3d) # size_3d ones in the matrix (each voxel is projected) - indptr = np.arange(0, size_3d+1, dim_proj) # each row has dim_proj ones + indptr = np.arange(0, size_3d + 1, dim_proj) # each row has dim_proj 1-entries if axis == 'z': self._log.debug('Projecting along the z-axis') coeff = [[1, 0, 0], [0, 1, 0]] @@ -622,36 +625,41 @@ class SimpleProjector(Projector): elif axis == 'y': self._log.debug('Projection along the y-axis') coeff = [[1, 0, 0], [0, 0, 1]] - indices = np.array([np.arange(row % dim_x, dim_x*dim_y, dim_x) + row//dim_x*dim_x*dim_y - for row in range(size_2d)]).reshape(-1) + indices = np.array( + [np.arange(row % dim_x, dim_x * dim_y, dim_x) + row // dim_x * dim_x * dim_y + for row in range(size_2d)]).reshape(-1) elif axis == 'x': self._log.debug('Projection along the x-axis') coeff = [[0, 0, 1], [0, 1, 0]] # Caution, coordinate switch: u, v --> z, y (not y, z!) - indices = np.array([np.arange(dim_x) + (row % dim_z)*dim_x*dim_y + row//dim_z*dim_x - for row in range(size_2d)]).reshape(-1) + indices = np.array( + [np.arange(dim_x) + (row % dim_z) * dim_x * dim_y + row // dim_z * dim_x + for row in range(size_2d)]).reshape(-1) + else: + raise ValueError('{} is not a valid axis parameter (use x, y or z)!'.format(axis)) if dim_uv is not None: - indptr = indptr.tolist() # convert to use insert() and append() - d_v = np.floor((dim_uv[0]-dim_v)/2), np.ceil((dim_uv[0]-dim_v)/2) # padding in v - d_u = np.floor((dim_uv[1]-dim_u)/2), np.ceil((dim_uv[1]-dim_u)/2) # padding in u - indptr.extend([indptr[-1]]*d_v[1]*dim_uv[1]) # add empty lines at the end + indptr = list(indptr) # convert to use insert() and append() + d_v = np.floor((dim_uv[0] - dim_v) / 2), np.ceil( + (dim_uv[0] - dim_v) / 2) # padding in v + d_u = np.floor((dim_uv[1] - dim_u) / 2), np.ceil( + (dim_uv[1] - dim_u) / 2) # padding in u + indptr.extend([indptr[-1]] * d_v[1] * dim_uv[1]) # add empty lines at the end for i in np.arange(dim_v, 0, -1): # all slices in between - up, lo = i*dim_u, (i-1)*dim_u # upper / lower slice end + up, lo = i * dim_u, (i - 1) * dim_u # upper / lower slice end indptr[up:up] = [indptr[up]] * d_u[1] # end of the slice indptr[lo:lo] = [indptr[lo]] * d_u[0] # start of the slice - indptr = [0]*d_v[0]*dim_uv[1] + indptr # insert empty rows at the beginning - size_2d = np.prod(dim_uv) # increase size_2d + indptr = [0] * d_v[0] * dim_uv[1] + indptr # insert empty rows at the beginning else: # Make sure dim_uv is defined (used for the assertion) dim_uv = dim_v, dim_u assert dim_uv[0] >= dim_v and dim_uv[1] >= dim_u, 'Projected dimensions are too small!' # Create weight-matrix: shape = (np.prod(dim_uv), np.prod(dim)) - self.sparsity = 1. - len(data)/np.prod(shape, dtype=np.float) + self.sparsity = 1. - len(data) / np.prod(shape, dtype=np.float) weight = csr_matrix((data, indices, indptr), shape=shape) super(SimpleProjector, self).__init__(dim, dim_uv, weight, coeff) - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) def get_info(self, verbose=False): - '''Get specific information about the projector as a string. + """Get specific information about the projector as a string. Parameters ---------- @@ -664,7 +672,7 @@ class SimpleProjector(Projector): info : string Information about the projector as a string, e.g. for the use in plot titles. - ''' + """ if verbose: return 'projected along {}-axis'.format(self.axis) else: diff --git a/pyramid/quaternion.py b/pyramid/quaternion.py index 3e02643..1267707 100644 --- a/pyramid/quaternion.py +++ b/pyramid/quaternion.py @@ -4,27 +4,27 @@ # """This module provides the :class:`~.Quaternion` class which can be used for rotations.""" - -import numpy as np - import logging +import numpy as np __all__ = ['Quaternion'] class Quaternion(object): - - '''Class representing a rotation expressed by a quaternion. + """Class representing a rotation expressed by a quaternion. A quaternion is a four-dimensional description of a rotation which can also be described by a rotation vector (`v1`, `v2`, `v3`) and a rotation angle :math:`\theta`. The four components are calculated to: + .. math:: - w = \cos(\theta/2) - x = v_1 \cdot \sin(\theta/2) - y = v_2 \cdot \sin(\theta/2) - z = v_3 \cdot \sin(\theta/2) + + w = \cos(\theta/2) + x = v_1 \cdot \sin(\theta/2) + y = v_2 \cdot \sin(\theta/2) + z = v_3 \cdot \sin(\theta/2) + Use the :func:`~.from_axisangle` and :func:`~.to_axisangle` to convert to axis-angle representation and vice versa. Quaternions can be multiplied by other quaternions, which results in a new rotation or with a vector, which results in a rotated vector. @@ -33,46 +33,44 @@ class Quaternion(object): ---------- values : float The four quaternion values `w`, `x`, `y`, `z`. - conj : :class:`~.Quaternion` - The conjugate of the quaternion, representing a tilt in opposite direction. - matrix : matrix - The rotation matrix representation of the quaternion - ''' + """ NORM_TOLERANCE = 1E-6 - _log = logging.getLogger(__name__+'.Quaternion') + _log = logging.getLogger(__name__ + '.Quaternion') @property def conj(self): + """The conjugate of the quaternion, representing a tilt in opposite direction.""" w, x, y, z = self.values return Quaternion((w, -x, -y, -z)) @property def matrix(self): + """The rotation matrix representation of the quaternion.""" w, x, y, z = self.values - return np.array([[1-2*(y**2+z**2), 2*(x*y-w*z), 2*(x*z+w*y)], - [2*(x*y+w*z), 1-2*(x**2+z**2), 2*(y*z-w*x)], - [2*(x*z-w*y), 2*(y*z+w*x), 1-2*(x**2+y**2)]]) + return np.array([[1 - 2 * (y ** 2 + z ** 2), 2 * (x * y - w * z), 2 * (x * z + w * y)], + [2 * (x * y + w * z), 1 - 2 * (x ** 2 + z ** 2), 2 * (y * z - w * x)], + [2 * (x * z - w * y), 2 * (y * z + w * x), 1 - 2 * (x ** 2 + y ** 2)]]) def __init__(self, values): self._log.debug('Calling __init__') self.values = values self._normalize() - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) def __mul__(self, other): # self * other self._log.debug('Calling __mul__') if isinstance(other, Quaternion): # Quaternion multiplication return self.dot_quat(self, other) elif len(other) == 3: # vector multiplication - q_vec = Quaternion((0,)+tuple(other)) + q_vec = Quaternion((0,) + tuple(other)) q = self.dot_quat(self.dot_quat(self, q_vec), self.conj) return q.values[1:] def dot_quat(self, q1, q2): - '''Multiply two :class:`~.Quaternion` objects to create a new one (always normalized). + """Multiply two :class:`~.Quaternion` objects to create a new one (always normalized). Parameters ---------- @@ -84,26 +82,26 @@ class Quaternion(object): quaternion : :class:`~.Quaternion` The resulting quaternion. - ''' + """ self._log.debug('Calling dot_quat') w1, x1, y1, z1 = q1.values w2, x2, y2, z2 = q2.values - w = w1*w2 - x1*x2 - y1*y2 - z1*z2 - x = w1*x2 + x1*w2 + y1*z2 - z1*y2 - y = w1*y2 + y1*w2 + z1*x2 - x1*z2 - z = w1*z2 + z1*w2 + x1*y2 - y1*x2 + w = w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2 + x = w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2 + y = w1 * y2 + y1 * w2 + z1 * x2 - x1 * z2 + z = w1 * z2 + z1 * w2 + x1 * y2 - y1 * x2 return Quaternion((w, x, y, z)) def _normalize(self): self._log.debug('Calling _normalize') - mag2 = np.sum(n**2 for n in self.values) + mag2 = np.sum(n ** 2 for n in self.values) if abs(mag2 - 1.0) > self.NORM_TOLERANCE: mag = np.sqrt(mag2) self.values = tuple(n / mag for n in self.values) @classmethod def from_axisangle(cls, vector, theta): - '''Create a quaternion from an axis-angle representation + """Create a quaternion from an axis-angle representation Parameters ---------- @@ -117,7 +115,7 @@ class Quaternion(object): quaternion : :class:`~.Quaternion` The resulting quaternion. - ''' + """ cls._log.debug('Calling from_axisangle') x, y, z = vector theta /= 2. @@ -128,18 +126,14 @@ class Quaternion(object): return cls((w, x, y, z)) def to_axisangle(self): - '''Convert the quaternion to axis-angle-representation. - - Parameters - ---------- - None + """Convert the quaternion to axis-angle-representation. Returns ------- vector, theta : :class:`~numpy.ndarray` (N=3), float Vector around which the rotation is executed and rotation angle. - ''' + """ self._log.debug('Calling to_axisangle') w, x, y, z = self.values theta = 2.0 * np.arccos(w) diff --git a/pyramid/ramp.py b/pyramid/ramp.py index c1f8aa2..ffe375f 100644 --- a/pyramid/ramp.py +++ b/pyramid/ramp.py @@ -4,18 +4,15 @@ # """This module provides the :class:`~.Ramp` class which implements polynomial phase ramps.""" - import numpy as np from pyramid.phasemap import PhaseMap - __all__ = ['Ramp'] class Ramp(object): - - '''Class representing a polynomial phase ramp. + """Class representing a polynomial phase ramp. Sometimes additional phase ramps occur in phase maps which do not stem from a magnetization distribution inside the FOV. This class allows the construction (and via the derivative @@ -48,7 +45,10 @@ class Ramp(object): After a reconstruction the relevant polynomial ramp information is stored in the `param_cache`. If a phasemap with index `i` in the DataSet should be corrected use: - >>> phase_map -= ramp(i, dof_list) + .. code-block:: python + + phase_map -= ramp(i=0, dof_list=[0, 1, 2]) + The optional parameter `dof_list` can be used to specify a list of degrees of freedom which should be used for the ramp (e.g. `[0]` will just apply the offset, `[0, 1, 2]` will apply @@ -58,7 +58,7 @@ class Ramp(object): features which stem from the magnetization could be covered by the polynom, decreasing the phase contribution of the magnetization distribution, leading to a false retrieval. - ''' + """ def __init__(self, data_set, order=None): self.data_set = data_set @@ -85,14 +85,12 @@ class Ramp(object): return PhaseMap(self.data_set.a, phase_ramp, mask=np.zeros(dim_uv, dtype=np.bool)) def jac_dot(self, index): - '''Calculate the product of the Jacobi matrix with a given `vector`. + """Calculate the product of the Jacobi matrix . Parameters ---------- - vector : :class:`~numpy.ndarray` (N=1) - Vectorized form of the 3D magnetization distribution. First the `x`, then the `y` and - lastly the `z` components are listed. Ramp parameters are also added at the end if - necessary. + index : int + Index of the phasemap from the `dataset` for which the phase ramp is calculated. Returns ------- @@ -100,7 +98,7 @@ class Ramp(object): Product of the Jacobi matrix (which is not explicitely calculated) with the input `vector`. Just the ramp contribution is calculated! - ''' + """ if self.order is None: # Do nothing if order is None! return 0 else: @@ -114,7 +112,7 @@ class Ramp(object): return np.ravel(phase_ramp) def jac_T_dot(self, vector): - ''''Calculate the transposed ramp parameters from a given `vector`. + """'Calculate the transposed ramp parameters from a given `vector`. Parameters ---------- @@ -126,21 +124,21 @@ class Ramp(object): result_vector : :class:`~numpy.ndarray` (N=1) Transposed ramp parameters. - ''' + """ result = [] hp = self.data_set.hook_points # Iterate over all degrees of freedom: for dof in range(self.deg_of_freedom): # Iterate over all projectors: for i, projector in enumerate(self.data_set.projectors): - sub_vec = vector[hp[i]:hp[i+1]] + sub_vec = vector[hp[i]:hp[i + 1]] poly_mesh = self.create_poly_mesh(self.data_set.a, dof, projector.dim_uv) # Transposed ramp parameters: summed product of the vector with the poly-mesh: result.append(np.sum(sub_vec * np.ravel(poly_mesh))) return result def extract_ramp_params(self, x): - '''Extract the ramp parameters of an input vector and return the rest. + """Extract the ramp parameters of an input vector and return the rest. Parameters ---------- @@ -159,7 +157,7 @@ class Ramp(object): ramp parameters are present so that other functions do not have to bother with them and the :class:`.~ramp` already knows all important parameters for its own functions. - ''' + """ if self.order is not None: # Do nothing if order is None! # Split off ramp parameters and fill cache: x, ramp_params = np.split(x, [-self.n]) @@ -168,7 +166,7 @@ class Ramp(object): @classmethod def create_poly_mesh(cls, a, deg_of_freedom, dim_uv): - '''Create a polynomial mesh for the ramp calculation for a specific degree of freedom. + """Create a polynomial mesh for the ramp calculation for a specific degree of freedom. Parameters ---------- @@ -186,7 +184,7 @@ class Ramp(object): result_mesh : :class:`~numpy.ndarray` (N=2) Polynomial mesh that was created and can be used for further calculations. - ''' + """ # Determine if u-direction (u_or_v == 1) or v-direction (u_or_v == 0)! u_or_v = (deg_of_freedom - 1) % 2 # Determine polynomial order: @@ -196,7 +194,7 @@ class Ramp(object): @classmethod def create_ramp(cls, a, dim_uv, params): - '''Class method to create an arbitrary polynomial ramp. + """Class method to create an arbitrary polynomial ramp. Parameters ---------- @@ -213,7 +211,7 @@ class Ramp(object): phase_ramp : :class:`~pyramid.phasemap.PhaseMap` The phase ramp as a :class:`~pyramid.phasemap.PhaseMap` object. - ''' + """ phase_ramp = np.zeros(dim_uv) dof_list = range(len(params)) for dof in dof_list: diff --git a/pyramid/reconstruction.py b/pyramid/reconstruction.py index 80271a1..d847a70 100644 --- a/pyramid/reconstruction.py +++ b/pyramid/reconstruction.py @@ -12,20 +12,18 @@ the distribution. """ +import logging import numpy as np from pyramid.magdata import MagData -import logging - - __all__ = ['optimize_linear', 'optimize_nonlin', 'optimize_splitbregman'] _log = logging.getLogger(__name__) def optimize_linear(costfunction, max_iter=None): - '''Reconstruct a three-dimensional magnetic distribution from given phase maps via the + """Reconstruct a three-dimensional magnetic distribution from given phase maps via the conjugate gradient optimizaion method :func:`~.scipy.sparse.linalg.cg`. Blazingly fast for l2-based cost functions. @@ -42,7 +40,7 @@ def optimize_linear(costfunction, max_iter=None): mag_data : :class:`~pyramid.magdata.MagData` The reconstructed magnetic distribution as a :class:`~.MagData` object. - ''' + """ import jutil.cg as jcg _log.debug('Calling optimize_linear') _log.info('Cost before optimization: {}'.format(costfunction(np.zeros(costfunction.n)))) @@ -58,7 +56,7 @@ def optimize_linear(costfunction, max_iter=None): def optimize_nonlin(costfunction, first_guess=None): - '''Reconstruct a three-dimensional magnetic distribution from given phase maps via + """Reconstruct a three-dimensional magnetic distribution from given phase maps via steepest descent method. This is slow, but works best for non l2-regularisators. @@ -75,7 +73,7 @@ def optimize_nonlin(costfunction, first_guess=None): mag_data : :class:`~pyramid.magdata.MagData` The reconstructed magnetic distribution as a :class:`~.MagData` object. - ''' + """ import jutil.minimizer as jmin import jutil.norms as jnorms _log.debug('Calling optimize_nonlin') @@ -90,7 +88,7 @@ def optimize_nonlin(costfunction, first_guess=None): q = 1. / (1. - (1. / p)) lq = jnorms.LPPow(q, 1e-20) - def preconditioner(_, direc): + def _preconditioner(_, direc): direc_p = direc / abs(direc).max() direc_p = 10 * (1. / q) * lq.jac(direc_p) return direc_p @@ -100,7 +98,7 @@ def optimize_nonlin(costfunction, first_guess=None): result = jmin.minimize( costfunction, x_0, method="SteepestDescent", - options={"preconditioner": preconditioner}, + options={"preconditioner": _preconditioner}, tol={"max_iteration": 10000}) x_opt = result.x _log.info('Cost after optimization: {}'.format(costfunction(x_opt))) @@ -110,7 +108,7 @@ def optimize_nonlin(costfunction, first_guess=None): def optimize_splitbregman(costfunction, weight, lam, mu): - ''' + """ Reconstructs magnet distribution from phase image measurements using a split bregman algorithm with a dedicated TV-l1 norm. Very dedicated, frickle, brittle, and difficult to get to work, but fastest option available if it works. @@ -134,7 +132,7 @@ def optimize_splitbregman(costfunction, weight, lam, mu): mag_data : :class:`~pyramid.magdata.MagData` The reconstructed magnetic distribution as a :class:`~.MagData` object. - ''' + """ import jutil.splitbregman as jsb import jutil.operator as joperator import jutil.diff as jdiff diff --git a/pyramid/regularisator.py b/pyramid/regularisator.py index bacc1d6..0952cbf 100644 --- a/pyramid/regularisator.py +++ b/pyramid/regularisator.py @@ -5,23 +5,21 @@ """This module provides the :class:`~.Regularisator` class which represents a regularisation term which adds additional constraints to a costfunction to minimize.""" +import abc +import logging import numpy as np from scipy import sparse -import abc -import jutil.norms as jnorm import jutil.diff as jdiff - -import logging - +import jutil.norms as jnorm __all__ = ['NoneRegularisator', 'ZeroOrderRegularisator', 'FirstOrderRegularisator', 'ComboRegularisator'] class Regularisator(object): - '''Class for providing a regularisation term which implements additional constraints. + """Class for providing a regularisation term which implements additional constraints. Represents a certain constraint for the 3D magnetization distribution whose cost is to minimize in addition to the derivation from the 2D phase maps. Important is the used `norm` and the @@ -40,10 +38,10 @@ class Regularisator(object): Number of additional parameters which are not used in the regularisation. Used to cut the input vector into the appropriate size. - ''' + """ __metaclass__ = abc.ABCMeta - _log = logging.getLogger(__name__+'.Regularisator') + _log = logging.getLogger(__name__ + '.Regularisator') @abc.abstractmethod def __init__(self, norm, lam, add_params=0): @@ -55,7 +53,7 @@ class Regularisator(object): self.slice = slice(-add_params) else: self.slice = slice(None) - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) def __call__(self, x): self._log.debug('Calling __call__') @@ -72,7 +70,7 @@ class Regularisator(object): self.add_params) def jac(self, x): - '''Calculate the derivative of the regularisation term for a given magnetic distribution. + """Calculate the derivative of the regularisation term for a given magnetic distribution. Parameters ---------- @@ -84,13 +82,13 @@ class Regularisator(object): result : :class:`~numpy.ndarray` (N=1) Jacobi vector which represents the cost derivative of all voxels of the magnetization. - ''' + """ result = np.zeros_like(x) result[self.slice] = self.lam * self.norm.jac(x[self.slice]) return result def hess_dot(self, x, vector): - '''Calculate the product of a `vector` with the Hessian matrix of the regularisation term. + """Calculate the product of a `vector` with the Hessian matrix of the regularisation term. Parameters ---------- @@ -107,13 +105,13 @@ class Regularisator(object): result : :class:`~numpy.ndarray` (N=1) Product of the input `vector` with the Hessian matrix. - ''' + """ result = np.zeros_like(vector) result[self.slice] = self.lam * self.norm.hess_dot(x, vector[self.slice]) return result def hess_diag(self, x): - ''' Return the diagonal of the Hessian. + """ Return the diagonal of the Hessian. Parameters ---------- @@ -128,7 +126,7 @@ class Regularisator(object): result : :class:`~numpy.ndarray` (N=1) Diagonal of the Hessian matrix. - ''' + """ self._log.debug('Calling hess_diag') result = np.zeros_like(x) result[self.slice] = self.lam * self.norm.hess_diag(x[self.slice]) @@ -136,8 +134,7 @@ class Regularisator(object): class ComboRegularisator(Regularisator): - - '''Class for providing a regularisation term which combines several regularisators. + """Class for providing a regularisation term which combines several regularisators. If more than one regularisation should be utilized, this class can be use. It is given a list of :class:`~.Regularisator` objects. The input will be forwarded to each of them and the @@ -148,12 +145,13 @@ class ComboRegularisator(Regularisator): reg_list: :class:`~.Regularisator` A list of regularisator objects to whom the input is passed on. - ''' + """ def __init__(self, reg_list): self._log.debug('Calling __init__') self.reg_list = reg_list - self._log.debug('Created '+str(self)) + super(ComboRegularisator, self).__init__(norm=None, lam=None) + self._log.debug('Created ' + str(self)) def __call__(self, x): self._log.debug('Calling __call__') @@ -165,10 +163,10 @@ class ComboRegularisator(Regularisator): def __str__(self): self._log.debug('Calling __str__') - return 'ComboRegularisator(reg_list=%s)' % (self.reg_list) + return 'ComboRegularisator(reg_list=%s)' % self.reg_list def jac(self, x): - '''Calculate the derivative of the regularisation term for a given magnetic distribution. + """Calculate the derivative of the regularisation term for a given magnetic distribution. Parameters ---------- @@ -180,11 +178,11 @@ class ComboRegularisator(Regularisator): result : :class:`~numpy.ndarray` (N=1) Jacobi vector which represents the cost derivative of all voxels of the magnetization. - ''' + """ return np.sum([self.reg_list[i].jac(x) for i in range(len(self.reg_list))], axis=0) def hess_dot(self, x, vector): - '''Calculate the product of a `vector` with the Hessian matrix of the regularisation term. + """Calculate the product of a `vector` with the Hessian matrix of the regularisation term. Parameters ---------- @@ -201,12 +199,12 @@ class ComboRegularisator(Regularisator): result : :class:`~numpy.ndarray` (N=1) Product of the input `vector` with the Hessian matrix. - ''' + """ return np.sum([self.reg_list[i].hess_dot(x, vector) for i in range(len(self.reg_list))], axis=0) def hess_diag(self, x): - ''' Return the diagonal of the Hessian. + """ Return the diagonal of the Hessian. Parameters ---------- @@ -221,13 +219,13 @@ class ComboRegularisator(Regularisator): result : :class:`~numpy.ndarray` (N=1) Diagonal of the Hessian matrix. - ''' + """ self._log.debug('Calling hess_diag') return np.sum([self.reg_list[i].hess_diag(x) for i in range(len(self.reg_list))], axis=0) class NoneRegularisator(Regularisator): - '''Placeholder class if no regularization is used. + """Placeholder class if no regularization is used. This class is instantiated in the :class:`~pyramid.costfunction.Costfunction`, which means no regularisation is used. All associated functions return appropriate zero-values. @@ -239,23 +237,24 @@ class NoneRegularisator(Regularisator): lam: 0 Not used. - ''' + """ - _log = logging.getLogger(__name__+'.NoneRegularisator') + _log = logging.getLogger(__name__ + '.NoneRegularisator') def __init__(self): self._log.debug('Calling __init__') self.norm = None self.lam = 0 self.add_params = None - self._log.debug('Created '+str(self)) + super(NoneRegularisator, self).__init__(norm=None, lam=None) + self._log.debug('Created ' + str(self)) def __call__(self, x): self._log.debug('Calling __call__') return 0 def jac(self, x): - '''Calculate the derivative of the regularisation term for a given magnetic distribution. + """Calculate the derivative of the regularisation term for a given magnetic distribution. Parameters ---------- @@ -267,11 +266,11 @@ class NoneRegularisator(Regularisator): result : :class:`~numpy.ndarray` (N=1) Jacobi vector which represents the cost derivative of all voxels of the magnetization. - ''' + """ return np.zeros_like(x) def hess_dot(self, x, vector): - '''Calculate the product of a `vector` with the Hessian matrix of the regularisation term. + """Calculate the product of a `vector` with the Hessian matrix of the regularisation term. Parameters ---------- @@ -280,7 +279,7 @@ class NoneRegularisator(Regularisator): is constant in this case, thus `x` can be set to None (it is not used in the computation). It is implemented for the case that in the future nonlinear problems have to be solved. - vector : :class:`~numpy.ndarray` (N=1) + vector : a :class:`~numpy.ndarray` (N=1) Vectorized magnetization distribution which is multiplied by the Hessian. Returns @@ -288,11 +287,11 @@ class NoneRegularisator(Regularisator): result : :class:`~numpy.ndarray` (N=1) Product of the input `vector` with the Hessian matrix of the costfunction. - ''' + """ return np.zeros_like(vector) def hess_diag(self, x): - ''' Return the diagonal of the Hessian. + """ Return the diagonal of the Hessian. Parameters ---------- @@ -307,13 +306,13 @@ class NoneRegularisator(Regularisator): result : :class:`~numpy.ndarray` (N=1) Diagonal of the Hessian matrix. - ''' + """ self._log.debug('Calling hess_diag') return np.zeros_like(x) class ZeroOrderRegularisator(Regularisator): - '''Class for providing a regularisation term which implements Lp norm minimization. + """Class for providing a regularisation term which implements Lp norm minimization. The constraint this class represents is the minimization of the Lp norm for the 3D magnetization distribution. Important is the regularisation parameter `lam` (lambda) which @@ -326,9 +325,9 @@ class ZeroOrderRegularisator(Regularisator): p: int, optional Order of the norm (default: 2, which means a standard L2-norm). - ''' + """ - _log = logging.getLogger(__name__+'.ZeroOrderRegularisator') + _log = logging.getLogger(__name__ + '.ZeroOrderRegularisator') def __init__(self, _=None, lam=1E-4, p=2, add_params=None): self._log.debug('Calling __init__') @@ -338,11 +337,11 @@ class ZeroOrderRegularisator(Regularisator): else: norm = jnorm.LPPow(p, 1e-12) super(ZeroOrderRegularisator, self).__init__(norm, lam, add_params) - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) class FirstOrderRegularisator(Regularisator): - '''Class for providing a regularisation term which implements derivation minimization. + """Class for providing a regularisation term which implements derivation minimization. The constraint this class represents is the minimization of the first order derivative of the 3D magnetization distribution using a Lp norm. Important is the regularisation parameter `lam` @@ -358,7 +357,7 @@ class FirstOrderRegularisator(Regularisator): p: int, optional Order of the norm (default: 2, which means a standard L2-norm). - ''' + """ def __init__(self, mask, lam=1E-4, p=2, add_params=None): self.p = p @@ -371,4 +370,4 @@ class FirstOrderRegularisator(Regularisator): else: norm = jnorm.WeightedTV(jnorm.LPPow(p, 1e-12), D, [D0.shape[0], D.shape[0]]) super(FirstOrderRegularisator, self).__init__(norm, lam, add_params) - self._log.debug('Created '+str(self)) + self._log.debug('Created ' + str(self)) diff --git a/pyramid/template.x3d b/pyramid/template.x3d deleted file mode 100644 index 1ab06c3..0000000 --- a/pyramid/template.x3d +++ /dev/null @@ -1,152 +0,0 @@ -<!DOCTYPE X3D PUBLIC 'ISO//Web3D//DTD X3D 3.2//EN' 'http://www.web3d.org/specifications/x3d-3.2.dtd'> -<X3D xmlns:cfn='_xml/_xsd/CommonFunctions' xmlns:cvs='CVSInfo' xmlns:fn='http://www.w3.org/2005/xpath-functions' xmlns:lfn='local_functions' xmlns:ss='urn:schemas-microsoft-com:office:spreadsheet' xmlns:v2kfn='_xml/_xsd/V2Kfunctions' xmlns:x3d='http://www.web3d.org/specifications/x3d-3.2.xsd' xmlns:xlink='http://www.w3.org/1999/xlink' xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' profile='Immersive' version='3.2' xsd:noNamespaceSchemaLocation='http://www.web3d.org/specifications/x3d-3.2.xsd'> - <Engine DEF='engine'> - <RenderJob DEF='render'> - <WindowGroup> - <Window position='10 50' size='933,700' fullScreen='false'/> - </WindowGroup> - </RenderJob> - </Engine> - <Scene> - <Background skyColor='0 0 0'/> - <ProximitySensor DEF='HereIAm' enabled='true' size='10000000 10000000 10000000'/> - <ProtoDeclare name='Spin_Proto'> - <ProtoInterface> - <field name='spin_position' accessType='inputOnly' type='SFVec3f'/> - <field name='spin_scale' accessType='inputOnly' type='SFVec3f'/> - <field name='spin_rotation' accessType='inputOnly' type='SFRotation'/> - <field name='spin_color' accessType='inputOnly' type='SFColor'/> - </ProtoInterface> - <ProtoBody> - <Group> - <Transform DEF='Spin'> - <IS> - <connect nodeField='scale' protoField='spin_scale'/> - <connect nodeField='translation' protoField='spin_position'/> - <connect nodeField='rotation' protoField='spin_rotation'/> - </IS> - <Transform translation='0 0.375 0'> - <Shape> - <Cone bottomRadius='0.25' bottom='true' solid='true' height='0.25' side='true'/> - <Appearance> - <Material DEF='ConeColor'> - <IS> - <connect nodeField='diffuseColor' protoField='spin_color'/> - </IS> - </Material> - </Appearance> - </Shape> - </Transform> - <Transform translation='0 -0.125 0'> - <Shape> - <Cylinder radius='0.1' height='0.75'/> - <Appearance> - <Material DEF='CylinderColor'> - <IS> - <connect nodeField='diffuseColor' protoField='spin_color'/> - </IS> - </Material> - </Appearance> - </Shape> - </Transform> - </Transform> - </Group> - </ProtoBody> - </ProtoDeclare> - <Transform DEF='ArrowsHUD'> - <Transform DEF='Arrows' translation='-4.5 -3 -10' scale='0.75 0.75 0.75'> - <Group DEF='ArrowGreen'> - <Shape> - <Cylinder DEF='ArrowCylinder' radius='0.025' top='false'/> - <Appearance DEF='Green'> - <Material diffuseColor='0 1 0'/> - </Appearance> - </Shape> - <Transform translation='0 1 0'> - <Shape> - <Cone DEF='ArrowCone' bottomRadius='0.05' height='0.1'/> - <Appearance USE='Green'/> - </Shape> - </Transform> - <Transform translation='0 1.1 0'> - <Billboard> - <Shape> - <Appearance DEF='LabelAppearance'> - <Material diffuseColor='1 1 0'/> - </Appearance> - <Text string='Y'> - <FontStyle DEF='LabelFont' size='0.25'/> - </Text> - </Shape> - </Billboard> - </Transform> - </Group> - <Group DEF='ArrowBlue'> - <Transform rotation='0 0 1 -1.57079'> - <Shape> - <Cylinder USE='ArrowCylinder'/> - <Appearance DEF='Blue'> - <Material diffuseColor='0 0 1'/> - </Appearance> - </Shape> - <Transform translation='0 1 0'> - <Shape> - <Cone USE='ArrowCone'/> - <Appearance USE='Blue'/> - </Shape> - </Transform> - <Transform rotation='0 0 1 1.57079' translation='0.072 1.1 0'> - <Billboard> - <Shape> - <Appearance USE='LabelAppearance'/> - <Text string='X'> - <FontStyle USE='LabelFont'/> - </Text> - </Shape> - </Billboard> - </Transform> - </Transform> - </Group> - <Group DEF='ArrowRed'> - <Transform rotation='1 0 0 1.57079'> - <Shape> - <Cylinder USE='ArrowCylinder'/> - <Appearance DEF='Red'> - <Material diffuseColor='1 0 0'/> - </Appearance> - </Shape> - <Transform translation='0 1 0'> - <Shape> - <Cone USE='ArrowCone'/> - <Appearance USE='Red'/> - </Shape> - </Transform> - <Transform rotation='1 0 0 -1.57079' translation='0 1.1 0.072'> - <Billboard> - <Shape> - <Appearance USE='LabelAppearance'/> - <Text string='Z'> - <FontStyle USE='LabelFont'/> - </Text> - </Shape> - </Billboard> - </Transform> - </Transform> - </Group> - </Transform> - </Transform> - <Script DEF='ChangeRot' > - <field accessType='inputOnly' type='SFRotation' name='orientation'/> - <field accessType='outputOnly' name='CoordRot' type='SFRotation'/> - <![CDATA[javascript: - function orientation(orientation){ - CoordRot= new SFRotation(orientation[0], orientation[1], orientation[2], -orientation[3]); - } - ]]> - <ROUTE fromNode='HereIAm' fromField='orientation_changed' toNode='ArrowsHUD' toField='rotation'/> - <ROUTE fromNode='HereIAm' fromField='position_changed' toNode='ArrowsHUD' toField='translation'/> - <ROUTE fromNode='HereIAm' fromField='orientation_changed' toNode='ChangeRot' toField='orientation'/> - <ROUTE fromNode='ChangeRot' fromField='CoordRot' toNode='Arrows' toField='set_rotation'/> -</Script> - </Scene> -</X3D> diff --git a/pyramid/tests/pep8_log.txt b/pyramid/tests/pep8_log.txt deleted file mode 100644 index 2b347a7..0000000 --- a/pyramid/tests/pep8_log.txt +++ /dev/null @@ -1,49 +0,0 @@ -<<< PEP8 LOGFILE >>> -RUN: 2016-02-21 15:25:44 -IGNORED RULES: E125, E226, E228, W503 -MAX LINE LENGTH: 99 - -ERRORS AND WARNINGS: -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_dat.py:19:1: E265 block comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_dat.py:33:1: E265 block comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_dat.py:39:1: E265 block comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_dat.py:63:1: E266 too many leading '#' for block comment -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_dat.py:65:1: E265 block comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_vtk.py:29:1: E731 do not assign a lambda expression, use a def -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_vtk.py:104:1: E266 too many leading '#' for block comment -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_vtk.py:105:1: E265 block comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_vtk.py:106:1: E265 block comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_vtk.py:108:1: E266 too many leading '#' for block comment -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_vtk.py:109:1: E265 block comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_vtk.py:110:1: E265 block comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_vtk.py:112:1: E265 block comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_vtk.py:113:1: E265 block comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_vtk.py:121:1: E265 block comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_vtk.py:133:5: E303 too many blank lines (2) -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_vtk.py:141:1: E115 expected an indented block (comment) -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_vtk.py:142:1: E115 expected an indented block (comment) -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_vtk.py:143:1: E115 expected an indented block (comment) -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_vtk.py:144:1: E115 expected an indented block (comment) -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_vtk.py:145:1: E115 expected an indented block (comment) -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\magdata\magdata_from_vtk.py:156:35: W292 no newline at end of file -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\phasemap\phasemap_from_dm3.py:30:1: E115 expected an indented block (comment) -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\phasemap\phasemap_from_dm3.py:32:41: E261 at least two spaces before inline comment -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\phasemap\phasemap_from_dm3.py:32:41: E262 inline comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\phasemap\phasemap_tilt_series.py:29:31: E261 at least two spaces before inline comment -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\phasemap\phasemap_tilt_series.py:29:31: E262 inline comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\phasemap\phasemap_tilt_series.py:31:1: E265 block comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\phasemap\phasemap_tilt_series.py:32:1: E265 block comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\phasemap\phasemap_tilt_series.py:34:1: E265 block comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\phasemap\phasemap_tilt_series.py:35:1: E265 block comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\phasemap\phasemap_tilt_series.py:36:1: E265 block comment should start with '# ' -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\phasemap\phasemap_tilt_series.py:59:30: W292 no newline at end of file -----> 33 PEP8 violations detected! - -TODOS: -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\pyramid\phasemapper.py: Why minus? -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\pyramid\phasemapper.py: Implement right! -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\pyramid\phasemapper.py: check if projector manages scalar multiplication (problem with MagData) and fix! -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\pyramid\tests\test_projector.py: Test RotTiltProjector!!! -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\scripts\reconstruction\reconstruction_3d_from_magdata.py: toggle multiprocessing if nprocs > 1 -C:\Users\Jan\Home\PhD Thesis\Spyder\Pyramid\pyramid\tests\test_projector.py: Test RotTiltProjector!!! -----> 6 TODOs found! diff --git a/pyramid/tests/test_analytic.py b/pyramid/tests/test_analytic.py index 7b7637f..401a4f2 100644 --- a/pyramid/tests/test_analytic.py +++ b/pyramid/tests/test_analytic.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """Testcase for the analytic module.""" - import os import unittest @@ -18,41 +17,42 @@ class TestCaseAnalytic(unittest.TestCase): path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_analytic/') dim = (4, 4, 4) a = 10.0 - phi = pi/4 - center = (dim[0]/2, dim[1]/2, dim[2]/2) - radius = dim[2]/4 + phi = pi / 4 + center = (dim[0] / 2, dim[1] / 2, dim[2] / 2) + radius = dim[2] / 4 def test_phase_mag_slab(self): - '''Test of the phase_mag_slab method.''' - width = (self.dim[0]/2, self.dim[1]/2, self.dim[2]/2) + """Test of the phase_mag_slab method.""" + width = (self.dim[0] / 2, self.dim[1] / 2, self.dim[2] / 2) phase = an.phase_mag_slab(self.dim, self.a, self.phi, self.center, width).phase reference = np.load(os.path.join(self.path, 'ref_phase_slab.npy')) - assert_allclose(phase, reference, err_msg='Unexpected behavior in phase_mag_slab()') + assert_allclose(phase, reference, err_msg='Unexpected behavior in phase_mag_slab()') def test_phase_mag_disc(self): - '''Test of the phase_mag_disc method.''' - radius = self.dim[2]/4 - height = self.dim[2]/2 + """Test of the phase_mag_disc method.""" + radius = self.dim[2] / 4 + height = self.dim[2] / 2 phase = an.phase_mag_disc(self.dim, self.a, self.phi, self.center, radius, height).phase reference = np.load(os.path.join(self.path, 'ref_phase_disc.npy')) - assert_allclose(phase, reference, err_msg='Unexpected behavior in phase_mag_disc()') + assert_allclose(phase, reference, err_msg='Unexpected behavior in phase_mag_disc()') def test_phase_mag_sphere(self): - '''Test of the phase_mag_sphere method.''' - radius = self.dim[2]/4 + """Test of the phase_mag_sphere method.""" + radius = self.dim[2] / 4 phase = an.phase_mag_sphere(self.dim, self.a, self.phi, self.center, radius).phase reference = np.load(os.path.join(self.path, 'ref_phase_sphere.npy')) - assert_allclose(phase, reference, err_msg='Unexpected behavior in phase_mag_sphere()', + assert_allclose(phase, reference, err_msg='Unexpected behavior in phase_mag_sphere()', atol=1E-10) def test_phase_mag_vortex(self): - '''Test of the phase_mag_vortex method.''' - radius = self.dim[2]/4 - height = self.dim[2]/2 + """Test of the phase_mag_vortex method.""" + radius = self.dim[2] / 4 + height = self.dim[2] / 2 phase = an.phase_mag_vortex(self.dim, self.a, self.center, radius, height).phase reference = np.load(os.path.join(self.path, 'ref_phase_vort.npy')) assert_allclose(phase, reference, err_msg='Unexpected behavior in phase_mag_vortex()') + if __name__ == '__main__': suite = unittest.TestLoader().loadTestsFromTestCase(TestCaseAnalytic) unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/pyramid/tests/test_costfunction.py b/pyramid/tests/test_costfunction.py index 4fe19c5..7e4b941 100644 --- a/pyramid/tests/test_costfunction.py +++ b/pyramid/tests/test_costfunction.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """Testcase for the costfunction module""" - import os import unittest @@ -9,15 +8,14 @@ import numpy as np from numpy.testing import assert_allclose from pyramid.costfunction import Costfunction -from pyramid.forwardmodel import ForwardModel from pyramid.dataset import DataSet -from pyramid.projector import SimpleProjector +from pyramid.forwardmodel import ForwardModel from pyramid.phasemap import PhaseMap +from pyramid.projector import SimpleProjector from pyramid.regularisator import FirstOrderRegularisator class TestCaseCostfunction(unittest.TestCase): - def setUp(self): self.path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_costfunction') self.a = 10. @@ -68,7 +66,7 @@ class TestCaseCostfunction(unittest.TestCase): assert_allclose(self.cost.hess_dot(None, np.ones(self.cost.n)), hess_vec_ref, atol=1E-7, err_msg='Unexpected behaviour in jac()!') hess = np.array([self.cost.hess_dot(None, np.eye(self.cost.n)[:, i]) - for i in range(self.cost.n)]).T + for i in range(self.cost.n)]).T hess_ref = np.load(os.path.join(self.path, 'hess_ref.npy')) assert_allclose(hess, hess_ref, atol=1E-7, err_msg='Unexpected behaviour in hess_dot()!') diff --git a/pyramid/tests/test_dataset.py b/pyramid/tests/test_dataset.py index 60bcfbd..3a3505a 100644 --- a/pyramid/tests/test_dataset.py +++ b/pyramid/tests/test_dataset.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- """Testcase for the dataset module""" +from __future__ import print_function import os import unittest @@ -9,13 +10,12 @@ import numpy as np from numpy.testing import assert_allclose from pyramid.dataset import DataSet -from pyramid.projector import SimpleProjector -from pyramid.phasemap import PhaseMap from pyramid.magdata import MagData +from pyramid.phasemap import PhaseMap +from pyramid.projector import SimpleProjector class TestCaseDataSet(unittest.TestCase): - def setUp(self): self.path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_dataset') self.a = 10. @@ -42,11 +42,9 @@ class TestCaseDataSet(unittest.TestCase): def test_create_phase_maps(self): self.data.projectors = [self.projector] - mag_data = MagData(self.a, np.ones((3,)+self.dim)) + mag_data = MagData(self.a, np.ones((3,) + self.dim)) self.data.phase_maps = self.data.create_phase_maps(mag_data) phase_vec_ref = np.load(os.path.join(self.path, 'phase_vec_ref.npy')) - print (self.data.phase_vec - phase_vec_ref).max() - print (self.data.phase_vec - phase_vec_ref).min() assert_allclose(self.data.phase_vec, phase_vec_ref, atol=1E-6, err_msg='Unexpected behaviour in create_phase_maps()!') @@ -67,7 +65,7 @@ class TestCaseDataSet(unittest.TestCase): self.data.set_Se_inv_diag_with_conf([confidence, confidence]) assert self.data.Se_inv.shape == (self.data.m, self.data.m), \ 'Unexpected behaviour in set_Se_inv_diag_with_masks()!' - assert self.data.Se_inv.diagonal().sum() == 2*confidence.sum(), \ + assert self.data.Se_inv.diagonal().sum() == 2 * confidence.sum(), \ 'Unexpected behaviour in set_Se_inv_diag_with_masks()!' def test_set_3d_mask(self): diff --git a/pyramid/tests/test_forwardmodel.py b/pyramid/tests/test_forwardmodel.py index b5b5869..b646600 100644 --- a/pyramid/tests/test_forwardmodel.py +++ b/pyramid/tests/test_forwardmodel.py @@ -1,21 +1,19 @@ # -*- coding: utf-8 -*- """Testcase for the forwardmodel module""" - import os import unittest import numpy as np from numpy.testing import assert_allclose -from pyramid.forwardmodel import ForwardModel from pyramid.dataset import DataSet -from pyramid.projector import SimpleProjector +from pyramid.forwardmodel import ForwardModel from pyramid.phasemap import PhaseMap +from pyramid.projector import SimpleProjector class TestCaseForwardModel(unittest.TestCase): - def setUp(self): self.path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_forwardmodel') self.a = 10. diff --git a/pyramid/tests/test_kernel.py b/pyramid/tests/test_kernel.py index 24b79df..b13ed80 100644 --- a/pyramid/tests/test_kernel.py +++ b/pyramid/tests/test_kernel.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """Testcase for the magdata module.""" - import os import unittest @@ -12,7 +11,6 @@ from pyramid.kernel import Kernel class TestCaseKernel(unittest.TestCase): - def setUp(self): self.path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_kernel') self.kernel = Kernel(1., dim_uv=(4, 4), b_0=1., geometry='disc') diff --git a/pyramid/tests/test_magcreator.py b/pyramid/tests/test_magcreator.py index 980d631..9d3ff7f 100644 --- a/pyramid/tests/test_magcreator.py +++ b/pyramid/tests/test_magcreator.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """Testcase for the magcreator module.""" - import os import unittest @@ -13,7 +12,6 @@ import pyramid.magcreator as mc class TestCaseMagCreator(unittest.TestCase): - path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_magcreator') def test_shape_slab(self): @@ -71,7 +69,7 @@ class TestCaseMagCreator(unittest.TestCase): def test_create_mag_dist_homog(self): mag_shape = mc.Shapes.disc((1, 10, 10), (0, 5, 5), 3, 1) - magnitude = mc.create_mag_dist_homog(mag_shape, pi/4) + magnitude = mc.create_mag_dist_homog(mag_shape, pi / 4) assert_allclose(magnitude, np.load(os.path.join(self.path, 'ref_mag_disc.npy')), err_msg='Created homog. magnetic distribution does not match expectation') diff --git a/pyramid/tests/test_magdata.py b/pyramid/tests/test_magdata.py index 253148c..23691e8 100644 --- a/pyramid/tests/test_magdata.py +++ b/pyramid/tests/test_magdata.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """Testcase for the magdata module.""" - import os import unittest @@ -12,7 +11,6 @@ from pyramid.magdata import MagData class TestCaseMagData(unittest.TestCase): - def setUp(self): self.path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_magdata') magnitude = np.zeros((3, 4, 4, 4)) @@ -31,7 +29,7 @@ class TestCaseMagData(unittest.TestCase): def test_scale_down(self): self.mag_data.scale_down() - reference = 1/8. * np.ones((3, 2, 2, 2)) + reference = 1 / 8. * np.ones((3, 2, 2, 2)) assert_allclose(self.mag_data.magnitude, reference, err_msg='Unexpected behavior in scale_down()!') assert_allclose(self.mag_data.a, 20, @@ -67,13 +65,13 @@ class TestCaseMagData(unittest.TestCase): def test_get_vector(self): mask = self.mag_data.get_mask() vector = self.mag_data.get_vector(mask) - reference = np.ones(np.sum(mask)*3) + reference = np.ones(np.sum(mask) * 3) assert_allclose(vector, reference, err_msg='Unexpected behavior in get_vector()!') def test_set_vector(self): mask = self.mag_data.get_mask() - vector = 2 * np.ones(np.sum(mask)*3) + vector = 2 * np.ones(np.sum(mask) * 3) self.mag_data.set_vector(vector, mask) reference = np.zeros((3, 4, 4, 4)) reference[:, 1:-1, 1:-1, 1:-1] = 2 diff --git a/pyramid/tests/test_phasemap.py b/pyramid/tests/test_phasemap.py index 28713a3..e376e62 100644 --- a/pyramid/tests/test_phasemap.py +++ b/pyramid/tests/test_phasemap.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """Testcase for the phasemap module.""" - import os import unittest @@ -12,7 +11,6 @@ from pyramid.phasemap import PhaseMap class TestCasePhaseMap(unittest.TestCase): - def setUp(self): self.path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_phasemap') phase = np.zeros((4, 4)) @@ -33,7 +31,7 @@ class TestCasePhaseMap(unittest.TestCase): def test_scale_down(self): self.phase_map.scale_down() - reference = 1/4. * np.ones((2, 2)) + reference = 1 / 4. * np.ones((2, 2)) assert_allclose(self.phase_map.phase, reference, err_msg='Unexpected behavior in scale_down()!') assert_allclose(self.phase_map.mask, np.zeros((2, 2), dtype=np.bool), diff --git a/pyramid/tests/test_phasemapper.py b/pyramid/tests/test_phasemapper.py index e42b20e..1b9f5fe 100644 --- a/pyramid/tests/test_phasemapper.py +++ b/pyramid/tests/test_phasemapper.py @@ -10,12 +10,11 @@ from numpy.testing import assert_allclose from pyramid.kernel import Kernel from pyramid.magdata import MagData from pyramid.phasemap import PhaseMap -from pyramid.phasemapper import PhaseMapperElectric, pm +from pyramid.phasemapper import PhaseMapperMIP, pm from pyramid.phasemapper import PhaseMapperRDFC, PhaseMapperRDRC, PhaseMapperFDFC class TestCasePhaseMapperRDFC(unittest.TestCase): - def setUp(self): self.path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_phasemapper') self.mag_proj = MagData.load_from_hdf5(os.path.join(self.path, 'mag_proj.hdf5')) @@ -54,7 +53,6 @@ class TestCasePhaseMapperRDFC(unittest.TestCase): class TestCasePhaseMapperRDRC(unittest.TestCase): - def setUp(self): self.path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_phasemapper') self.mag_proj = MagData.load_from_hdf5(os.path.join(self.path, 'mag_proj.hdf5')) @@ -93,7 +91,6 @@ class TestCasePhaseMapperRDRC(unittest.TestCase): class TestCasePhaseMapperFDFC(unittest.TestCase): - def setUp(self): self.path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_phasemapper') self.mag_proj = MagData.load_from_hdf5(os.path.join(self.path, 'mag_proj.hdf5')) @@ -128,11 +125,10 @@ class TestCasePhaseMapperFDFC(unittest.TestCase): class TestCasePhaseMapperElectric(unittest.TestCase): - def setUp(self): self.path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_phasemapper') self.mag_proj = MagData.load_from_hdf5(os.path.join(self.path, 'mag_proj.hdf5')) - self.mapper = PhaseMapperElectric(self.mag_proj.a, self.mag_proj.dim[1:]) + self.mapper = PhaseMapperMIP(self.mag_proj.a, self.mag_proj.dim[1:]) def tearDown(self): self.path = None @@ -150,7 +146,6 @@ class TestCasePhaseMapperElectric(unittest.TestCase): class TestCasePM(unittest.TestCase): - def setUp(self): self.path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_phasemapper') self.mag_proj = MagData.load_from_hdf5(os.path.join(self.path, 'mag_proj.hdf5')) diff --git a/pyramid/tests/test_projector.py b/pyramid/tests/test_projector.py index 008e774..7463afd 100644 --- a/pyramid/tests/test_projector.py +++ b/pyramid/tests/test_projector.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """Testcase for the projector module.""" - import os import unittest @@ -9,12 +8,11 @@ import numpy as np from numpy import pi from numpy.testing import assert_allclose -from pyramid.projector import XTiltProjector, YTiltProjector, SimpleProjector from pyramid.magdata import MagData +from pyramid.projector import XTiltProjector, YTiltProjector, SimpleProjector class TestCaseSimpleProjector(unittest.TestCase): - def setUp(self): self.path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_projector') self.mag_data = MagData.load_from_hdf5(os.path.join(self.path, 'ref_mag_data.hdf5')) @@ -45,9 +43,9 @@ class TestCaseSimpleProjector(unittest.TestCase): def test_SimpleProjector_jac_dot(self): mag_vec = self.mag_data.mag_vec - mag_proj_z = self.proj_z.jac_dot(mag_vec).reshape((2,)+self.proj_z.dim_uv) - mag_proj_y = self.proj_y.jac_dot(mag_vec).reshape((2,)+self.proj_y.dim_uv) - mag_proj_x = self.proj_x.jac_dot(mag_vec).reshape((2,)+self.proj_x.dim_uv) + mag_proj_z = self.proj_z.jac_dot(mag_vec).reshape((2,) + self.proj_z.dim_uv) + mag_proj_y = self.proj_y.jac_dot(mag_vec).reshape((2,) + self.proj_y.dim_uv) + mag_proj_x = self.proj_x.jac_dot(mag_vec).reshape((2,) + self.proj_x.dim_uv) mag_proj_z_ref = MagData.load_from_hdf5(os.path.join(self.path, 'ref_mag_proj_z.hdf5')) mag_proj_y_ref = MagData.load_from_hdf5(os.path.join(self.path, 'ref_mag_proj_y.hdf5')) mag_proj_x_ref = MagData.load_from_hdf5(os.path.join(self.path, 'ref_mag_proj_x.hdf5')) @@ -92,13 +90,12 @@ class TestCaseSimpleProjector(unittest.TestCase): class TestCaseXTiltProjector(unittest.TestCase): - def setUp(self): self.path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_projector') self.mag_data = MagData.load_from_hdf5(os.path.join(self.path, 'ref_mag_data.hdf5')) self.proj_00 = XTiltProjector(self.mag_data.dim, tilt=0) - self.proj_45 = XTiltProjector(self.mag_data.dim, tilt=pi/4) - self.proj_90 = XTiltProjector(self.mag_data.dim, tilt=pi/2) + self.proj_45 = XTiltProjector(self.mag_data.dim, tilt=pi / 4) + self.proj_90 = XTiltProjector(self.mag_data.dim, tilt=pi / 2) def tearDown(self): self.path = None @@ -123,9 +120,9 @@ class TestCaseXTiltProjector(unittest.TestCase): def test_XTiltProjector_jac_dot(self): mag_vec = self.mag_data.mag_vec - mag_proj_00 = self.proj_00.jac_dot(mag_vec).reshape((2,)+self.proj_00.dim_uv) - mag_proj_45 = self.proj_45.jac_dot(mag_vec).reshape((2,)+self.proj_45.dim_uv) - mag_proj_90 = self.proj_90.jac_dot(mag_vec).reshape((2,)+self.proj_90.dim_uv) + mag_proj_00 = self.proj_00.jac_dot(mag_vec).reshape((2,) + self.proj_00.dim_uv) + mag_proj_45 = self.proj_45.jac_dot(mag_vec).reshape((2,) + self.proj_45.dim_uv) + mag_proj_90 = self.proj_90.jac_dot(mag_vec).reshape((2,) + self.proj_90.dim_uv) mag_proj_00_ref = MagData.load_from_hdf5(os.path.join(self.path, 'ref_mag_proj_x00.hdf5')) mag_proj_45_ref = MagData.load_from_hdf5(os.path.join(self.path, 'ref_mag_proj_x45.hdf5')) mag_proj_90_ref = MagData.load_from_hdf5(os.path.join(self.path, 'ref_mag_proj_x90.hdf5')) @@ -170,13 +167,12 @@ class TestCaseXTiltProjector(unittest.TestCase): class TestCaseYTiltProjector(unittest.TestCase): - def setUp(self): self.path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_projector') self.mag_data = MagData.load_from_hdf5(os.path.join(self.path, 'ref_mag_data.hdf5')) self.proj_00 = YTiltProjector(self.mag_data.dim, tilt=0) - self.proj_45 = YTiltProjector(self.mag_data.dim, tilt=pi/4) - self.proj_90 = YTiltProjector(self.mag_data.dim, tilt=pi/2) + self.proj_45 = YTiltProjector(self.mag_data.dim, tilt=pi / 4) + self.proj_90 = YTiltProjector(self.mag_data.dim, tilt=pi / 2) def tearDown(self): self.path = None @@ -201,9 +197,9 @@ class TestCaseYTiltProjector(unittest.TestCase): def test_XTiltProjector_jac_dot(self): mag_vec = self.mag_data.mag_vec - mag_proj_00 = self.proj_00.jac_dot(mag_vec).reshape((2,)+self.proj_00.dim_uv) - mag_proj_45 = self.proj_45.jac_dot(mag_vec).reshape((2,)+self.proj_45.dim_uv) - mag_proj_90 = self.proj_90.jac_dot(mag_vec).reshape((2,)+self.proj_90.dim_uv) + mag_proj_00 = self.proj_00.jac_dot(mag_vec).reshape((2,) + self.proj_00.dim_uv) + mag_proj_45 = self.proj_45.jac_dot(mag_vec).reshape((2,) + self.proj_45.dim_uv) + mag_proj_90 = self.proj_90.jac_dot(mag_vec).reshape((2,) + self.proj_90.dim_uv) mag_proj_00_ref = MagData.load_from_hdf5(os.path.join(self.path, 'ref_mag_proj_y00.hdf5')) mag_proj_45_ref = MagData.load_from_hdf5(os.path.join(self.path, 'ref_mag_proj_y45.hdf5')) mag_proj_90_ref = MagData.load_from_hdf5(os.path.join(self.path, 'ref_mag_proj_y90.hdf5')) @@ -246,6 +242,7 @@ class TestCaseYTiltProjector(unittest.TestCase): assert_allclose(jac_T_90, jac_T_90_ref, err_msg='Unexpected behaviour in the the transp. jacobi matrix! (90°)') + # TODO: Test RotTiltProjector!!! if __name__ == '__main__': diff --git a/pyramid/tests/test_regularisator.py b/pyramid/tests/test_regularisator.py index 656ff94..814dd76 100644 --- a/pyramid/tests/test_regularisator.py +++ b/pyramid/tests/test_regularisator.py @@ -1,20 +1,18 @@ # -*- coding: utf-8 -*- """Testcase for the regularisator module""" - import os import unittest import numpy as np from numpy.testing import assert_allclose +from pyramid.regularisator import FirstOrderRegularisator from pyramid.regularisator import NoneRegularisator from pyramid.regularisator import ZeroOrderRegularisator -from pyramid.regularisator import FirstOrderRegularisator class TestCaseNoneRegularisator(unittest.TestCase): - def setUp(self): self.n = 9 self.reg = NoneRegularisator() @@ -41,7 +39,6 @@ class TestCaseNoneRegularisator(unittest.TestCase): class TestCaseZeroOrderRegularisator(unittest.TestCase): - def setUp(self): self.n = 9 self.lam = 1 @@ -53,28 +50,27 @@ class TestCaseZeroOrderRegularisator(unittest.TestCase): self.reg = None def test_call(self): - assert_allclose(self.reg(np.arange(self.n)), np.sum(np.arange(self.n)**2), + assert_allclose(self.reg(np.arange(self.n)), np.sum(np.arange(self.n) ** 2), err_msg='Unexpected behaviour in __call__()!') def test_jac(self): - assert_allclose(self.reg.jac(np.arange(self.n)), 2*np.arange(self.n), + assert_allclose(self.reg.jac(np.arange(self.n)), 2 * np.arange(self.n), err_msg='Unexpected behaviour in jac()!') jac = np.array([self.reg.jac(np.eye(self.n)[:, i]) for i in range(self.n)]).T - assert_allclose(jac, 2*np.eye(self.n), err_msg='Unexpected behaviour in jac()!') + assert_allclose(jac, 2 * np.eye(self.n), err_msg='Unexpected behaviour in jac()!') def test_hess_dot(self): - assert_allclose(self.reg.hess_dot(None, np.arange(self.n)), 2*np.arange(self.n), + assert_allclose(self.reg.hess_dot(None, np.arange(self.n)), 2 * np.arange(self.n), err_msg='Unexpected behaviour in jac()!') hess = np.array([self.reg.hess_dot(None, np.eye(self.n)[:, i]) for i in range(self.n)]).T - assert_allclose(hess, 2*np.eye(self.n), err_msg='Unexpected behaviour in hess_dot()!') + assert_allclose(hess, 2 * np.eye(self.n), err_msg='Unexpected behaviour in hess_dot()!') def test_hess_diag(self): - assert_allclose(self.reg.hess_diag(np.arange(self.n)), 2*np.ones(self.n), + assert_allclose(self.reg.hess_diag(np.arange(self.n)), 2 * np.ones(self.n), err_msg='Unexpected behaviour in hess_diag()!') class TestCaseFirstOrderRegularisator(unittest.TestCase): - def setUp(self): self.path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_regularisator') self.dim = (4, 5, 6) @@ -128,8 +124,8 @@ class TestCaseFirstOrderRegularisator(unittest.TestCase): err_msg='Unexpected behaviour in hess_dot()!') def test_hess_diag(self): - hess_diag = self.reg.hess_diag(np.ones(3*self.n)) # derivatives in all directions! - hess_diag_ref = np.zeros(3*self.n) # derivatives in all directions! + hess_diag = self.reg.hess_diag(np.ones(3 * self.n)) # derivatives in all directions! + hess_diag_ref = np.zeros(3 * self.n) # derivatives in all directions! first_order_jac_ref = np.load(os.path.join(self.path, 'first_order_jac_ref.npy')) hess_diag_ref[0:self.n] = np.diag(first_order_jac_ref) assert_allclose(hess_diag, hess_diag_ref, atol=1E-7, diff --git a/pyramid/version.py b/pyramid/version.py index 690ef13..f7b63cf 100644 --- a/pyramid/version.py +++ b/pyramid/version.py @@ -1,3 +1,4 @@ -# THIS FILE IS GENERATED BY THE PYRAMID SETUP.PY -version = "0.1.0-dev" -hg_revision = "7d3c2ba238ff+" +# -*- coding: utf-8 -*- +"""This file is generated automatically by the Pyramid `setup.py`""" +version = '0.1.0-dev' +hg_revision = 'a7afcc233730+' diff --git a/scripts/gui/mag_slicer.py b/scripts/gui/mag_slicer.py index cd3af7a..90200f4 100644 --- a/scripts/gui/mag_slicer.py +++ b/scripts/gui/mag_slicer.py @@ -12,15 +12,13 @@ import os import sys from PyQt4 import QtCore, QtGui - from matplotlibwidget import MatplotlibWidget import pyramid +from pyramid.kernel import Kernel from pyramid.magdata import MagData -from pyramid.projector import SimpleProjector from pyramid.phasemapper import PhaseMapperRDFC -from pyramid.kernel import Kernel - +from pyramid.projector import SimpleProjector try: _fromUtf8 = QtCore.QString.fromUtf8 diff --git a/scripts/reconstruction/reconstruction_3d_from_magdata.py b/scripts/reconstruction/reconstruction_3d_from_magdata.py index 1cfcf3a..3d0cb3b 100644 --- a/scripts/reconstruction/reconstruction_3d_from_magdata.py +++ b/scripts/reconstruction/reconstruction_3d_from_magdata.py @@ -1,13 +1,13 @@ # -*- coding: utf-8 -*- """Reconstruct a magnetization distributions from phase maps created from it.""" +import logging.config +import multiprocessing as mp import numpy as np -import multiprocessing as mp + import pyramid as pr from jutil.taketime import TakeTime -import logging.config - logging.config.fileConfig(pr.LOGGING_CONFIG, disable_existing_loggers=False) @@ -34,7 +34,7 @@ if __name__ == '__main__': mp.freeze_support() # Load magnetization distribution: - mag_data = pr.MagData.load_from_netcdf4(mag_name+'.nc') + mag_data = pr.MagData.load_from_hdf5(mag_name + '.hdf5') dim = mag_data.dim # Construct data set and regularisator: diff --git a/setup.py b/setup.py index cf80528..3d455d0 100644 --- a/setup.py +++ b/setup.py @@ -1,17 +1,20 @@ #!python +# coding=utf-8 """Setup for testing, building, distributing and installing the 'Pyramid'-package""" +from __future__ import print_function import os +import re import subprocess import sys -import re -import numpy from distutils.command.build import build + +import numpy +from Cython.Distutils import build_ext from setuptools import setup, find_packages from setuptools.extension import Extension -from Cython.Distutils import build_ext -import hyperspy.api as hs # analysis:ignore + # Import Hyperspy before actually doing stuff, to set the PyQT API at the very beginning (to 2). # If this is not done, something sets it to 1 befor HyperSpy is imported, which leads to errors. @@ -28,6 +31,19 @@ LONG_DESCRIPTION = 'long description (TODO!)' # TODO: Long description! def get_package_version(package): + """Return the package version of the specified package. + + Parameters + ---------- + package: basestring + Name of the package whic should be checked. + + Returns + ------- + version: tuple (N=3) + Version number as a tuple. + + """ version = [] for version_attr in ('version', 'VERSION', '__version__'): if (hasattr(package, version_attr) and @@ -42,6 +58,7 @@ def get_package_version(package): def check_requirements(): + """Checks the requirements of the Pyramid package.""" if sys.version_info < PYTHON_VERSION: raise SystemExit('You need Python version %d.%d or later.' % PYTHON_VERSION) @@ -57,10 +74,18 @@ def check_requirements(): dep_error = True if dep_error: raise ImportError('You need `%s` version %d.%d or later.' - % ((package_name, ) + min_version)) + % ((package_name,) + min_version)) def hg_version(): + """Get the Mercurial reference identifier. + + Returns + ------- + hg_ref: basestring + The Mercurial reference identifier. + + """ try: hg_rev = subprocess.check_output(['hg', 'id', '--id']).strip() except: @@ -69,15 +94,37 @@ def hg_version(): def write_version_py(filename='pyramid/version.py'): - version_string = "# THIS FILE IS GENERATED BY THE PYRAMID SETUP.PY\n" + \ - 'version = "{}"\n'.format(VERSION) + \ - 'hg_revision = "{}"\n'.format(hg_version()) + """Write the version.py file. + + Parameters + ---------- + filename: basestring, optional + Write the version and hg_revision into the specified python file. + Defaults to 'pyramid/version.py'. + + """ + version_string = '# -*- coding: utf-8 -*-\n' + \ + '"""This file is generated automatically by the Pyramid `setup.py`"""\n' + \ + 'version = \'{}\'\n'.format(VERSION) + \ + 'hg_revision = \'{}\'\n'.format(hg_version()) with open(os.path.join(os.path.dirname(__file__), filename), 'w') as vfile: vfile.write(version_string) def get_files(rootdir): - '''Returns a list of .py-files inside rootdir''' + """Returns a list of .py-files inside rootdir. + + Parameters + ---------- + rootdir: basestring + Root directory in which to search for ``.py``-files. + + Returns + ------- + filepaths: list + List of filepaths which were found. + + """ filepaths = [] for root, dirs, files in os.walk(rootdir): for filename in files: @@ -86,10 +133,10 @@ def get_files(rootdir): return filepaths -print '\n-------------------------------------------------------------------------------' -print 'checking requirements' +print('\n-------------------------------------------------------------------------------') +print('checking requirements') check_requirements() -print 'write version.py' +print('write version.py') write_version_py() setup(name=DISTNAME, description=DESCRIPTION, @@ -101,7 +148,7 @@ setup(name=DISTNAME, version=VERSION, packages=find_packages(exclude=['tests']), include_dirs=[numpy.get_include()], - requires=['numpy', 'matplotlib', 'mayavi', 'hyperspy'], + requires=['numpy', 'matplotlib', 'mayavi', 'hyperspy', 'PIL', 'scipy', 'pyfftw', 'Cython'], scripts=get_files('scripts'), test_suite='nose.collector', cmdclass={'build_ext': build_ext, 'build': build}, @@ -111,6 +158,6 @@ setup(name=DISTNAME, include_dirs=[numpy.get_include()], extra_compile_args=['-march=native', '-mtune=native'] ) - ] + ] ) -print '-------------------------------------------------------------------------------\n' +print('-------------------------------------------------------------------------------\n') -- GitLab