Merge branch 'devel'
epsi-builds/msspec_python3/pipeline/head There was a failure building this commit Details

This commit is contained in:
Sylvain Tricot 2021-09-24 16:36:53 +02:00
commit 75784d4c01
36 changed files with 1378 additions and 740 deletions

View File

@ -1,22 +1,24 @@
# Get the base Python image
FROM python:latest
# Install system dependencies
RUN apt-get update && apt-get install -y virtualenv gfortran libgtk-3-dev nano
# Add a non-privileged user
RUN useradd -ms /bin/bash -d /opt/msspec msspec
# Set the working directory in the container
WORKDIR /code
USER msspec
RUN mkdir -p /opt/msspec/code
WORKDIR /opt/msspec/code
# Fetch the code
RUN git clone --branch devel https://git.ipr.univ-rennes1.fr/epsi/msspec_python3.git .
# Install system dependencies
RUN apt-get update && apt-get install -y virtualenv gfortran libgtk-3-dev
#COPY --chown=msspec:msspec . .
# Install msspec
ENV PATH=/opt/bin:$PATH
RUN make install VERBOSE=1 INSTALL_PREFIX=/opt
# Add a non-privileged user
RUN useradd -ms /bin/bash msspec
USER msspec
ENV PATH=/opt/msspec/.local/bin:$PATH
RUN make install VERBOSE=1
# Run the msspec frontend command on startup
ENTRYPOINT ["msspec"]

View File

@ -11,7 +11,7 @@ pybinding:
venv:
ifeq ($(NO_VENV),0)
@virtualenv --python=$(PYTHON_EXE) --prompt="(msspec-$(VERSION)) " $(VENV_PATH)
@$(INSIDE_VENV) pip install --upgrade pip && pip install -r src/pip.freeze
$(INSIDE_VENV) wget https://bootstrap.pypa.io/get-pip.py && python get-pip.py && pip install -r src/pip.freeze && rm -f get-pip.py
endif
@ -27,7 +27,7 @@ devel: venv pybinding wx
@$(INSIDE_VENV) pip install -e src/
wx:
_build_wx/wxPython.target:
@$(INSIDE_VENV) echo "Building wxPython for your `python --version 2>&1` under Linux $(DISTRO_RELEASE)..."
# Create a folder to build wx into
@mkdir -p _build_wx
@ -40,16 +40,22 @@ wx:
cd `ls -d wxPython*/`; \
pip install requests; \
python build.py dox etg --nodoc sip build bdist_wheel; \
ln -s `readlink -f dist/wxPython*.whl` ../; \
ln -sf `readlink -f dist/wxPython*.whl` ../; \
fi;
# Finally touch a dummy file to avoid phony target
@touch _build_wx/wxPython.target
wx: _build_wx/wxPython.target
# Install the wheel
@$(INSIDE_VENV) cd _build_wx && pip install wxPython*.whl
doc:
doc: VENV_PATH = ./_venv
doc: venv
@echo "Building pdf and html documentation..."
@$(INSIDE_VENV) pip install sphinx
@+$(INSIDE_VENV) $(MAKE) -C doc/ latexpdf
# @+$(INSIDE_VENV) $(MAKE) -C doc/ latexpdf
@+$(INSIDE_VENV) $(MAKE) -C doc/ html

View File

@ -4,8 +4,8 @@ Introduction
This is the Python MsSpec version with support for Python 3.x and dynamic memory allocation for Phagen and Spec
Installation of the devel package
=================================
Installation
============
Requirements
------------
@ -42,13 +42,14 @@ you need to install it.
Fetching the code
-----------------
You first need to clone the devel branch with either 2 commands below:
You first need to clone the repository with the command below:
```Bash
git clone https://git.ipr.univ-rennes1.fr/epsi/msspec_python3.git
git checkout devel
```
If you want to pull the devel branch (unstable):
```Bash
git clone --branch devel https://git.ipr.univ-rennes1.fr/epsi/msspec_python3.git
```
@ -61,21 +62,22 @@ One step install
----------------
The command below will do all the stuff to install msspec in its dedicated Python
virtual environment provided all the above requirements are fullfilled
virtual environment provided all the above requirements are fullfilled:
```Bash
cd msspec_python3
make devel
make install
```
This will:
- Create a Python virtual environment in the "\_venv" folder inside the msspec\_python3 folder.
- Create a Python virtual environment in your '~/.local/src' folder
- Install all the required Python packages in this virtual environment.
- Install (or even maybe build) wxPython for your OS and Python version in this virtual environment.
- Build the msspec shared librarires.
- Install msspec in *edit mode* in this virtual environment.
- Install the Python msspec package in this virtual environment.
- Install a frontend script called 'msspec' in the '~/.local/bin' folder.
You can tweak the process by specifying space separated key=value pairs on the command line.
Allowed keys are:
@ -89,35 +91,61 @@ Allowed keys are:
- FC, the Fortran compiler to use (gfortran)
- F2PY
Work with msspec
----------------
All you need to do each time you want to work with msspec is activating the virtual environment.
For example, if *virtualenv* was used to create the virtual environment:
To install msspec in developpment mode, use:
```Bash
source msspec_python3/_venv/bin/activate
cd msspec_python3
make devel
```
Then you can launch your script with
This will do the same steps as above except that the virtual environment will be located in
the "\_venv" folder inside the "msspec\_python3" folder and the frontend script will not be
installed.
Working with msspec
-------------------
Use the frontend command to process a Python script with msspec.
```Bash
python myscript.py
msspec -p myscript.py
```
This will execute the myscript.py inside the msspec virtual environment.
You can also load a hdf5 file with the '-l' option:
```Bash
msspec -l results.hdf5
```
You can load an iPython console with "msspec -i". It is a good way to modify the virtual environment
of MsSpec since you can add or remove packages withe the "%pip" command.
If you want to activate the MsSpec virtual environment in your current shell session:
```Bash
eval $(msspec -e)
```
You can then run scripts using the 'python' command directly.
Type in 'deactivate' to go back to your standard shell.
See the online [tutorials](https://msspec.cnrs.fr/tutorials/index.html) for more information on how to use msspec.
When you're done, you can deactivate the virtual environment with
```Bash
deactivate
```
Uninstall MsSpec
----------------
To remove MsSpec, use the command:
```Bash
msspec -u
```
This will simply remove the virtual environment folder in '~/.local/src' and the frontend script in '~/.local/bin'.
When Installed in "devel mode", nothing is created outside the msspec\_python3 folder, so you just have to remove
that folder to get rid of msspec on your computer

View File

@ -44,7 +44,6 @@ clean:
@rm -f source/spectroscopies/common_parameters.inc
@rm -f source/spectroscopies/ped/ped_parameters.inc
@rm -f source/spectroscopies/eig/eig_parameters.inc
@rm -f source/downloads.rst

View File

@ -258,7 +258,7 @@ texinfo_documents = [
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
custom.generate_download_page()
#custom.generate_download_page()
custom.generate_parameters()
custom.generate_parameters(spectroscopy='PED')
custom.generate_parameters(spectroscopy='EIG')

View File

@ -29,6 +29,9 @@ def generate_download_page():
Download and install notes
##########################
.. warning::
The content of this page is outdated. An updated version will be soon available.
click :download:`here <{}>` to download the last version of MsSpec and
:download:`here <{}>` for this website as a single pdf file

150
doc/source/downloads.rst Normal file
View File

@ -0,0 +1,150 @@
.. |LINUXSCRIPT| replace:: https://git.ipr.univ-rennes1.fr/epsi/msspec_python3/raw/branch/devel/utils/dockerized/linux/msspec
##########################
Download and install notes
##########################
************
Installation
************
There are 2 ways to install MsSpec. You can either:
- Use a Docker image. This is, by far, the most straightforward and easy way to work with MsSpec.
- Compile your own version for your system.
1. Using a Docker image
-----------------------
You first need `Docker <https://www.docker.com>`_ to be installed on your system.
This is really straightforward. Please see the `Docker documentation
<https://docs.docker.com/engine/install/>`_ for more information depending on
your OS.
* **For Linux**,
* Download :download:`this script <../../utils/dockerized/linux/msspec>` and
make it executable (with the *chmod u+x msspec* command)
* Place it in a location known to your $PATH (or add this location to your $PATH if needed).
The *~/.local/bin* folder is a good choice.
* **For Windows**
* You need a running X server. Download and install `VcXsrv <https://sourceforge.net/projects/vcxsrv/>`_
* Install the small :download:`MsSpec frontend <../../utils/dockerized/windows/msspec_setup.exe>`
* While not necessary, it is also a good idea to use a better terminal application than the default one.
`Windows Terminal <https://www.microsoft.com/fr-fr/p/windows-terminal/9n0dx20hk701#activetab=pivot:overviewtab>`_
may be a good choice.
* **For Mac**
* *To be documented*
Open a terminal in Linux, or a powershell in Windows and type in::
msspec
The first time you run the command, it will download the msspec image (it may takes several minutes or half an hour
depending on your internet connexion).
The command will automatically create a new container and start it.
As the command was entered without any argument on the command-line, the help message should be printed on the screen
.. code-block:: text
Usage: 1) msspec -p [PYTHON OPTIONS] SCRIPT [ARGUMENTS...]
2) msspec [-l FILE | -i | -h]
3) msspec [bash | reset]
Form (1) is used to launch a script
Form (2) is used to load a hdf5 data file
Form (3) is used to control the Docker container/image.
List of possible options:
-p Pass every arguments after this option to the msspec
virtual environment Python interpreter.
-i Run the interactive Python interpreter within msspec
virtual environment.
-l Load and display a *.hdf5 data file in a graphical
window.
-v Print the version.
-h Show this help message.
bash This command starts an interactive bash shell in the
MsSpec container.
reset This command removes the MsSpec container (but not the
image). Changes made in the container will be lost and
any new call to msspec will recreate a new fresh container.
2. Compile your own version
---------------------------
To install MsSpec this way, follow the instructions `here <https://git.ipr.univ-rennes1.fr/epsi/msspec_python3/src/branch/devel>`_
***************************
Running your Python scripts
***************************
You can run your MsSpec Python scripts (e.g. *my_script.py*) by typing in::
msspec -p my_script.py
This command is equivalent to activating the Python virtual environment MsSpec is intsalled in
and to run the Python interpreter of that environment (everything that follows the -p option is
passed to the python command).
You can also launch the Interactive Python (iPython) of MsSpec::
msspec -i
Inside this interactive session, you can run a script with the command::
%run my_script.py
You can interact with your filesystem with the classical *cd*, *ls*, *cp*, *rm*... commands.
and you can edit your script with::
%ed my_script.py
.. warning::
**If using the Docker image of MsSpec in Linux**, your home folder on the host machine is bind mounted
in the same location in the container and your UID and GID are also set so that creating files within
your home file hierarchy is totally transparent.
**If using the Docker image of MsSpec in Windows**, the drive containing your "My Documents" folder on the
host machine is bind mounted on the container at the root of the filesystem. For example, if your
"My documents" folder on Windows are in 'D:\\Home\\Bob\\MyDocuments', it will be available in the container as
'/D/Home/Bob/MyDocuments'. It has two consequences:
#. The msspec command will fail if running on another drive than the one where is located "My Documents"
#. You have to specify filenames with the Unix slashes. For example if you want to run the script located
in *.\\results\\my_script.py*, you will have to enter *msspec -p ./results/my_script.py*
**************
Uninstallation
**************
* **Under Linux**, type in::
msspec -u
* **Under Windows**, simply `uninstall the application from the Settings page
<https://support.microsoft.com/en-us/windows/uninstall-or-remove-apps-and-programs-in-windows-10-4b55f974-2cc6-2d2b-d092-5905080eaf98>`_.
A command window will pop-up and you will have to answer 'y' to remove MsSpec.
* **Under Mac OS**, *to be documented.*

View File

@ -7,4 +7,5 @@ FAQ
.. toctree::
hemispherical_cluster/hemispherical_cluster
coverage_report/coverage_report
.. coverage_report/coverage_report

View File

@ -135,7 +135,6 @@ Table of Contents
.. only:: html
##################

View File

@ -1,124 +0,0 @@
************
Installation
************
.. |logowin| image:: windows_icon.png
:height: 96px
:target: `win10_install_notes`_
.. |logolinux| image:: linux_icon.png
:height: 96px
:target: `linux_install_notes`_
.. |logomac| image:: apple_icon.png
:height: 96px
:target: `mac_install_notes`_
.. admonition:: Select your Operating System to view specific installation instructions
|logowin| |logolinux| |logomac|
.. _common_install_notes:
In a terminal window, execute the setup program you've just downloaded.
.. code-block:: console
$ sh ./MsSpec-version.setup
Once the install process has competed, you can launch the MsSpec environnement by typing::
msspec
.. _win10_install_notes:
For Windows 10
==============
Windows users can install MsSpec through the Windows Subsystem for Linux
(also known as bash Ubuntu).
Below is a short description of the steps to enable this feature. You can
have more details `here <https://docs.microsoft.com/en-us/windows/wsl/install-win10>`_.
Install the Windows Subsystem for Linux
---------------------------------------
1. Turn on Developer Mode
Open **Settings -> Update and Security -> For developers**
.. figure:: win_step1.png
:align: center
:width: 70%
Select the Developer Mode radio button
2. Open a command prompt. Run::
bash
.. figure:: win_step2.png
:align: center
:width: 70%
Type "y" to accept the license. An Ubuntu system will be installed.
3. Launch a new Ubuntu shell by running *bash* from the command prompt.
If this is the first time that the Windows Subsystem for Linux is installed,
you will be prompted to create a UNIX user. Simply follow the instructions.
This UNIX username and password may be different from your Windows username
and password.
Install an X server
-------------------
To allow graphical windows to popup in this Linux environnement, you need to install
an X server. **Xming** is a good choice. Go to `this website <http://www.straightrunning.com/XmingNotes/>`_
and download and install the public version 6.9.0.31.
Don't forget to start the server after the install. You can configure it to always run automatically at
the startup.
Install MsSpec
--------------
Open a Windows command prompt and launch *bash*. For the Xming server to work, you need to modify
the DISPLAY environnement variable. Enter this command::
echo "export DISPLAY=:0" >> ~/.bashrc && source ~/.bashrc
Then you can launch the setup program::
cd /where/the/setup/program/was/downloaded
sh ./MsSpec-version.setup
where *version* is the actual version number
.. _linux_install_notes:
For Linux
=========
Ubuntu and Mageia based dstributions are supported by the installer, but any Linux
flavour should be able to run MsSpec as long as you have permissions to install
all requirements.
You just need to open a terminal window and execute the setup program.
.. _mac_install_notes:
For Mac 0S
==========
.. note::
to be written...

View File

@ -1,6 +0,0 @@
:orphan:
.. automodule:: config
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,6 @@
:orphan:
.. automodule:: looper
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,6 @@
:orphan:
.. automodule:: version
:members:
:undoc-members:
:show-inheritance:

View File

@ -1,181 +1,130 @@
# coding: utf-8
# coding: utf8
from msspec.utils import *
from ase.build import bulk
from ase.visualize import view
import numpy as np
from msspec.calculator import MSSPEC, XRaySource
from msspec.iodata import Data
from itertools import product
from msspec.utils import hemispherical_cluster, get_atom_index
DATA = None
def AlN_cluster(emitter_tag, emitter_plane, diameter=0, planes=0, term_anion=True, tetra_down=True):
"""
This function is a kind of overload of the hemispherical_cluster function with specific attributes
to the AlN structure
:param emitter_tag: An integer that allows to identify the kind of atom to use as the emitter
:param emitter_plane: The plane where the emitter is. 0 means the surface.
:param diameter: The diameter of the cluster (in Angstroms).
:param planes: The total number of planes.
:param term_anion: True if the surface plane is anion terminated, False otherwise
:param tetra_down: The orientation of the tetrahedral
:return:
"""
# create the initial cluster of AlN
cluster = bulk('AlN', crystalstructure='wurtzite', a=3.11, c=4.975)
# tag each atom in the unit cell because they are all in a different chemical/geometrical environment
# (0 and 2 for Aluminum's atoms and 1 and 3 for Nitride's atoms)
[atom.set('tag', i) for i, atom in enumerate(cluster)]
# change the orientation of the tetrahedron
if not tetra_down:
cluster.rotate(180, 'y')
# From this base pattern, creat an hemispherically shaped cluster
cluster = hemispherical_cluster(cluster, emitter_tag=emitter_tag, emitter_plane=emitter_plane, diameter=diameter,
planes=planes)
# Depending on the number of planes above the emitter, the termination may not be the one you wish,
# we test this and raise an exception in such a case
# Get the termination by finding the kind of one atom located at the topmost z coordinate
termination = cluster[np.argsort(cluster.get_positions()[:, 2])[-1]].symbol
# test if the combination of parameters is possible
assert (termination == 'N' and term_anion) or (termination == 'Al' and not term_anion), (
"This termination isn't compatible with your others parameters, you must change the tag of "
"your emitter, the plane of your emitter or your termination")
return cluster
def create_clusters(side='Al', emitter='Al', diameter=15, planes=6):
clusters = []
def create_clusters(nplanes=6):
def get_AlN_tags_planes(side, emitter):
AlN = bulk('AlN', crystalstructure='wurtzite', a=3.11, c=4.975)
[atom.set('tag', i) for i, atom in enumerate(AlN)]
if side == 'Al':
term_anion = tetra_down = False
elif side == 'N':
term_anion = tetra_down = True
AlN.rotate([0,0,1],[0,0,-1])
Al_planes = range(0, nplanes, 2)
N_planes = range(1, nplanes, 2)
else:
N_planes = range(0, nplanes, 2)
Al_planes = range(1, nplanes, 2)
if emitter == 'Al':
tags = [0, 2]
planes = Al_planes
else:
tags = [1, 3]
planes = N_planes
return AlN, tags, planes
clusters = []
for side in ('Al', 'N'):
for emitter in ('Al', 'N'):
AlN, tags, planes = get_AlN_tags_planes(side, emitter)
for emitter_tag in tags:
for emitter_plane in planes:
cluster = hemispherical_cluster(AlN,
emitter_tag=emitter_tag,
emitter_plane=emitter_plane,
planes=emitter_plane+2)
cluster.absorber = get_atom_index(cluster, 0, 0, 0)
cluster.info.update({
'emitter_plane': emitter_plane,
'emitter_tag' : emitter_tag,
'emitter' : emitter,
'side' : side,
})
clusters.append(cluster)
print("Added cluster {}-side, emitter {}(tag {:d}) in "
"plane #{:d}".format(side, emitter, emitter_tag,
emitter_plane))
return clusters
def compute(clusters, theta=np.arange(-20., 80., 1.), phi=0.):
data = None
for ic, cluster in enumerate(clusters):
# Retrieve info from cluster object
side = cluster.info['side']
emitter = cluster.info['emitter']
plane = cluster.info['emitter_plane']
tag = cluster.info['emitter_tag']
# Set the level and the kinetic energy
if emitter == 'Al':
tags = (0, 2)
level = '2p'
ke = 1407.
elif emitter == 'N':
tags = (1, 3)
level = '1s'
ke = 1083.
for emitter_tag, emitter_plane in product(tags, range(0, planes)):
nplanes = emitter_plane + 2
try:
cluster = AlN_cluster(emitter_tag, emitter_plane, diameter=diameter, planes=nplanes, term_anion=term_anion,
tetra_down=tetra_down)
except AssertionError:
continue
cluster.absorber = get_atom_index(cluster, 0, 0, 0)
cluster.info.update({'emitter_plane': emitter_plane,
'emitter_tag': emitter_tag,
'emitter': emitter,
'side': side,
'level': level,
'ke': ke})
clusters.append(cluster)
calc = MSSPEC(spectroscopy='PED', algorithm='expansion')
return clusters
def compute_polar_scans(clusters, theta=np.arange(-20., 80., 1.), phi=0., data=DATA):
for ic, cluster in enumerate(clusters):
# select the spectroscopy of the calculation and create a new folder for each calculation
side, emitter, tag, plane, level, ke = [cluster.info[k] for k in ('side', 'emitter', 'emitter_tag',
'emitter_plane', 'level', 'ke')]
calc = MSSPEC(spectroscopy='PED', folder='calc{:0>3d}_S{}_E{}_T{:d}_P{:d}'.format(ic, side, emitter, tag,
plane))
calc.calculation_parameters.scattering_order = max(1, min(4, plane))
calc.source_parameters.energy = XRaySource.AL_KALPHA
calc.source_parameters.theta = -35
calc.detector_parameters.angular_acceptance = 4.
calc.detector_parameters.average_sampling = 'medium'
calc.calculation_parameters.scattering_order = max(1, min(4, plane))
calc.calculation_parameters.path_filtering = 'forward_scattering'
calc.calculation_parameters.off_cone_events = 1
[a.set('forward_angle', 30.) for a in cluster]
calc.calculation_parameters.vibrational_damping = 'averaged_tl'
[a.set('mean_square_vibration', 0.006) for a in cluster]
calc.set_atoms(cluster)
data = calc.get_theta_scan(level=level, theta=theta, phi=phi, kinetic_energy=ke, data=data)
data = calc.get_theta_scan(level=level, theta=theta, phi=phi,
kinetic_energy=ke, data=data)
dset = data[-1]
dset.title = 'Polar scan {emitter:s}({level:s} tag {tag:d}) in plane #{plane:d}'.format(emitter=emitter,
level=level, tag=tag,
plane=plane)
for name, value in cluster.info.items():
dset.add_parameter(group='AlnTuto', name=name, value=str(value), unit="")
#data.save('all_polar_scans.hdf5', append=True)
data.save('all_polar_scans.hdf5')
dset.title = "\'{}\' side - {}({}) tag #{:d}, plane #{:d}".format(
side, emitter, level, tag, plane)
def analysis(filename='all_polar_scans.hdf5'):
data=Data.load(filename)
# create datasets to store the sum of all emitter
return data
def analysis(data):
tmp_data = {}
for dset in data:
# retrieve some info
side = dset.get_parameter(group='AlnTuto', name='side')['value']
emitter = dset.get_parameter(group='AlnTuto', name='emitter')['value']
info = dset.get_cluster().info
side = info['side']
emitter = info['emitter']
try:
key = '{}_{}'.format(side, emitter)
tmp_data[key] += dset.cross_section
except KeyError:
tmp_data[key] = dset.cross_section.copy()
# get the index of theta = 0;
it0 = np.where(dset.theta == 0)[0][0]
for key, cs in tmp_data.items():
tmp_data[key + '_norm'] = cs / cs[it0]
tmp_data['Al_side'] = tmp_data['Al_Al_norm'] / tmp_data['Al_N_norm']
tmp_data['N_side'] = tmp_data['N_Al_norm'] / tmp_data['N_N_norm']
tmp_data['theta'] = dset.theta.copy()
tmp_data['Al_side'] = tmp_data['Al_Al'] / tmp_data['Al_N']
tmp_data['N_side'] = tmp_data['N_Al'] / tmp_data['N_N']
# now add all columns
substrate_dset = data.add_dset('Total substrate signal')
substrate_dset.add_columns(theta=dset.theta.copy())
substrate_dset.add_columns(**tmp_data)
view = substrate_dset.add_view('Al side',
title=r'AlN Polar scan in the (10$\bar{1}$0) azimuthal plane - Al side polarity',
xlabel=r'$\Theta (\degree$)',
ylabel='Signal (a.u.)')
view.select('theta', 'Al_Al_norm', legend='Al 2p')
view.select('theta', 'Al_N_norm', legend='N 1s')
view.set_plot_options(autoscale=True)
view = substrate_dset.add_view('N side',
title=r'AlN Polar scan in the (10$\bar{1}$0) azimuthal plane - N side polarity',
xlabel=r'$\Theta (\degree$)',
ylabel='Signal (a.u.)')
view.select('theta', 'N_Al_norm', legend='Al 2p')
view.select('theta', 'N_N_norm', legend='N 1s')
view.set_plot_options(autoscale=True)
view = substrate_dset.add_view('Ratios',
title=r'Al(2p)/N(1s) ratios on both polar sides of AlN in the (10$\bar{1}$0) '
title=r'Al(2p)/N(1s) ratios on both polar '
r'sides of AlN in the (10$\bar{1}$0) '
r'azimuthal plane',
xlabel=r'$\Theta (\degree$)',
ylabel='Intenisty ratio')
view.select('theta', 'Al_side', legend='Al side', where="theta >= 0 and theta <=70")
view.select('theta', 'N_side', legend='N side', where="theta >= 0 and theta <=70")
view.select('theta', 'Al_side', legend='Al side',
where="theta >= 0 and theta <=70")
view.select('theta', 'N_side', legend='N side',
where="theta >= 0 and theta <=70")
view.set_plot_options(autoscale=True)
data.save('analysis.hdf5')
data.view()
return data
DIAMETER = 10
PLANES = 4
clusters = create_clusters(side='Al', emitter='Al', diameter=DIAMETER, planes=PLANES) + \
create_clusters(side='Al', emitter='N', diameter=DIAMETER, planes=PLANES) + \
create_clusters(side='N', emitter='Al', diameter=DIAMETER, planes=PLANES) + \
create_clusters(side='N', emitter='N', diameter=DIAMETER, planes=PLANES)
compute_polar_scans(clusters, phi=0.)
analysis()
clusters = create_clusters()
data = compute(clusters)
data = analysis(data)
data.view()

View File

@ -1,54 +1,25 @@
# -*- encoding: utf-8 -*-
# vim: set fdm=indent ts=4 sw=4 sts=4 et ai tw=80 cc=+0 mouse=a nu : #
from msspec.calculator import MSSPEC, XRaySource
from msspec.utils import *
# coding: utf8
from msspec.calculator import MSSPEC
from ase.build import fcc111, add_adsorbate
from ase.visualize import view
from msspec.iodata import cols2matrix
from matplotlib import pyplot as plt
import numpy as np
import sys
data = None
all_z = np.arange(1.10, 1.50, 0.02)
all_z=(1.1,)
all_z = np.arange(1.10, 1.65, 0.05)
for zi, z0 in enumerate(all_z):
# construct the cluster
cluster = fcc111('Rh', size = (2,2,1))
add_adsorbate(cluster, 'O', z0, position = 'fcc')
cluster.pop(3)
#cluster.rotate('z',np.pi/3.)
#view(cluster)
add_adsorbate(cluster, 'O', z0, position = 'fcc')
cluster.absorber = len(cluster) - 1
calc = MSSPEC(spectroscopy = 'PED', folder = './RhO_z')
# Define a calculator
calc = MSSPEC(spectroscopy='PED', algorithm='inversion')
calc.set_atoms(cluster)
calc.calculation_parameters.scattering_order = 3
calc.calculation_parameters.RA_cutoff = 1
calc.source_parameters.energy = XRaySource.AL_KALPHA
# compute
level = '1s'
ke = 723.
data = calc.get_theta_phi_scan(level=level, kinetic_energy=ke, data=data)
# OPTIONAL, this will create an image of the data that you can combine
# in an animated gif
# Compute
data = calc.get_theta_phi_scan(level='1s', kinetic_energy=723, data=data)
dset = data[-1]
theta, phi, Xsec = cols2matrix(dset.theta, dset.phi, dset.cross_section)
X, Y = np.meshgrid(np.radians(phi), 2*np.tan(np.radians(theta/2.)))
fig = plt.figure()
ax = fig.add_subplot(111, projection='polar')
im = ax.pcolormesh(X, Y, Xsec)
theta_ticks = np.arange(0, 91, 15)
plt.yticks(2 * np.tan(np.radians(theta_ticks/2.)), theta_ticks)
plt.title(r"$z_0 = {:.2f} \AA$".format(z0))
plt.savefig('image{:03d}.png'.format(zi))
dset.title = "{:d}) z = {:.2f} angstroms".format(zi, z0)
data.view()

View File

@ -1,31 +1,17 @@
# -*- encoding: utf-8 -*-
# vim: set fdm=indent ts=4 sw=4 sts=4 et ai tw=80 cc=+0 mouse=a nu : #
from msspec.calculator import MSSPEC, XRaySource
from msspec.utils import *
# coding: utf8
from msspec.calculator import MSSPEC
from ase import Atoms
import numpy as np
# Create an atomic chain O-Rh
cluster = Atoms(['O', 'Rh'], positions = [(0,0,0), (0,0,4.)])
# Defining global variables
a0 = 6.0
symbols = ('Rh', 'O')
ke = 723.
level = '1s'
# Create the calculator
calc = MSSPEC(spectroscopy = 'PED')
calc.set_atoms(cluster)
cluster.absorber = 0
data = None
for symbol in symbols:
cluster = Atoms(symbol*2, positions = [(0,0,0), (0,0,a0)])
[a.set('mt_radius', 1.5) for a in cluster]
# Create the calculator
calc = MSSPEC(spectroscopy = 'PED')
calc.source_parameters.energy = XRaySource.AL_KALPHA
calc.set_atoms(cluster)
cluster.absorber = 0
# compute
data = calc.get_scattering_factors(level=level, kinetic_energy=ke, data=data)
# compute
data = calc.get_scattering_factors(level='1s', kinetic_energy=723)
data.view()

View File

@ -82,13 +82,13 @@ Here is the script for the computation. (:download:`download <RhO.py>`)
.. literalinclude:: RhO.py
:linenos:
.. note::
After runing this script, you will get 20 images in your folder. You can merge them in one animated gif image
like this:
.. code-block:: bash
convert -delay 50 -loop 0 image*.png animation.gif
.. .. note::
.. After runing this script, you will get 20 images in your folder. You can merge them in one animated gif image
.. like this:
..
.. .. code-block:: bash
..
.. convert -delay 50 -loop 0 image*.png animation.gif
.. seealso::

View File

@ -1,7 +1,7 @@
# coding: utf-8
# coding: utf8
from msspec.calculator import MSSPEC
from msspec.utils import *
from msspec.utils import hemispherical_cluster, get_atom_index
from ase.build import bulk
from ase.visualize import view
@ -9,20 +9,15 @@ from ase.visualize import view
a0 = 3.6 # The lattice parameter in angstroms
# Create the copper cubic cell
cluster = bulk('Cu', a=a0, cubic=True)
# Repeat the cell many times along x, y and z
cluster = cluster.repeat((4, 4, 4))
# Put the center of the structure at the origin
center_cluster(cluster)
# Keep atoms inside a given radius
cluster = cut_sphere(cluster, radius=a0 + .01)
# Keep only atoms below the plane z <= 0
cluster = cut_plane(cluster, z=0.1)
copper = bulk('Cu', a=a0, cubic=True)
cluster = hemispherical_cluster(copper, planes=3, emitter_plane=2)
# Set the absorber (the deepest atom centered in the xy-plane)
cluster.absorber = get_atom_index(cluster, 0, 0, -a0)
cluster.absorber = get_atom_index(cluster, 0, 0, 0)
# Create a calculator for the PhotoElectron Diffration
calc = MSSPEC(spectroscopy='PED')
# Set the cluster to use for the calculation
calc.set_atoms(cluster)
@ -31,4 +26,6 @@ data = calc.get_theta_scan(level='2p3/2')
# Show the results
data.view()
#calc.shutdown()
# Clean temporary files
calc.shutdown()

View File

@ -16,7 +16,7 @@ Begin by typing:
:linenos:
:lineno-start: 1
# coding: utf-8
# coding: utf8
from msspec.calculator import MSSPEC
from msspec.utils import *
@ -45,27 +45,37 @@ This is the job of the *ase* module, so load the module
from ase.build import bulk
from ase.visualize import view
a0 = 3.6
cluster = bulk('Cu', a = a0, cubic = True)
a0 = 3.6 # The lattice parameter in angstroms
# Create the copper cubic cell
copper = bulk('Cu', a=a0, cubic=True)
view(cluster)
In line 6 we load the :py:func:`bulk` function to create our atomic object and,
in line 7, we load the :py:func:`view` function to actually view our cluster.
The creation of the cluster is done line 10. The :py:func:`bulk` needs one
argument which are the chemical species ('Cu' in our example). We also pass 2
keyword (optional) arguments here:
The creation of the cluster starts on line 12. We create first the copper cubic
cell with the The :py:func:`bulk` function. It needs one argument which are the
chemical species ('Cu' in our example). We also pass 2 keyword (optional) arguments
here:
* The lattice parameter *a* in units of angströms.
* The *cubic* keyword, to obtain a cubic cell rather than the fully
reduced one which is not cubic
From now on, you can save your script as 'Cu.py' and open a terminal window in
the same directory as this file. Launch your script using python:
the same directory as this file. Launch your script using 'python' or 'msspec -p'
(depending on your installation):
.. code-block:: bash
python2 Cu.py
python Cu.py
or
.. code-block:: bash
msspec -p Cu.py
and a graphical window (the ase-gui) should open with a cubic cell of copper
like this one:
@ -80,34 +90,38 @@ like this one:
Obviously, multiple scattering calculations need more atoms to be accurate. Due
to the forward focusing effect in photo-electron diffraction, the best suited
geometry for the cluster is hemispherical. Obtaining such a cluster is a
straightforward process:
1. Repeat the previous cell in all 3 directions
2. center the structure
3. Keep only atoms within a given radius from center
4. Keep only atoms within one halh of the sphere.
straightforward process thanks to the :py:func:`utils.hemispherical_cluster` function.
This function will basically create a cluster based on a pattern (the cubic copper
cell here).
Modify your script like this and run it again.
.. literalinclude:: Cu_simple.py
.. literalinclude:: Cu.py
:linenos:
:lineno-start: 1
:lines: 1-21
:lines: 1-13
Don't forget to add the line to view the cluster at the end of the script and run
the script again.
the script again. The :py:func:`hemispherical_cluster` works in 3 simple steps:
#. Repeat the given *pattern* in all 3 directions
#. Center this new set of atoms and cut a sphere from the center
#. Remove the upper half of the created 'sphere'.
To get more information about how to use this function, have a look at the :ref:`hemispherical_cluster_faq` section in the :ref:`faq`.
.. figure:: Cu_fig2.png
:align: center
:width: 60%
Figure 2. The different steps to output a cluster.
a) After repeat, b) after cut_sphere, c) after cut_plane
a) After repeat, b) after cutting a sphere, c) final cluster
Once you a cluster is built the next step is to define which atom in the cluster
will absorbe the light. This atom is called the *absorber*.
Once your cluster is built the next step is to define which atom in the cluster
will absorb the light. This atom is called the *absorber* (or the *emitter* since
it emits the photoelectron).
To specify which atom is the absorber, you need to understand that the cluster
object is like a list of atoms. Each member of this list is an atom with its
@ -115,7 +129,7 @@ own position. You need to locate the index of the atom in the list that you want
it to be the absorber. Then, put that number in the *cluster.absorber* attribute
For example, suppose that you want the first atom of the list to be the
absorber. You should write:
absorber. You would write:
.. code-block:: python
@ -123,24 +137,27 @@ absorber. You should write:
To find what is the index of the atom you'd like to be the absorber, you can
either get it while you are visualizing the structure within the ase-gui
program. Or, you can use :py:func:`get_atom_index` function. This function takes
4 arguments: the cluster to look the index for, and the x, y and z coordinates.
program (select an atom with the left mouse button and look at its index in the
status line). Or, you can use :py:func:`utils.get_atom_index` function. This function
takes 4 arguments: the cluster to look the index for, and the x, y and z coordinates.
It will return the index of the closest atom to these coordinates. In our
example, to get the deepest atom centered in the xy-plane, we write:
example, as we used the :py:func:`utils.hemispherical_cluster` function to create our
cluster, the *emitter* (*absorber*) is always located at the origin, so defining it
is straightforward:
.. literalinclude:: Cu_simple.py
.. literalinclude:: Cu.py
:linenos:
:lineno-start: 22
:lines: 22-23
:lineno-start: 15
:lines: 15-16
That's all for the cluster part. We now need to create a calculator for that
object. This is a 2 lines procedure:
.. literalinclude:: Cu_simple.py
.. literalinclude:: Cu.py
:linenos:
:lineno-start: 24
:lines: 24-28
:lineno-start: 18
:lines: 18-22
When creating a new calculator, you must choose the kind of spectroscopy you
will work with. In this example we choose 'PED' for *PhotoElectron Diffraction*.
@ -153,14 +170,14 @@ Other types of spectroscopies are:
Now that everything is ready you can actually perform a calculation. The 2 lines
Now that everything is ready you can actually perform a calculation. The lines
below will produce a polar scan of the Cu(2p3/2) level with default parameters,
store the results in the data object and display it in a graphical window.
.. literalinclude:: Cu_simple.py
.. literalinclude:: Cu.py
:linenos:
:lineno-start: 29
:lines: 29-33
:lineno-start: 24
:lines: 24-28
running this script will produce the following output
@ -177,7 +194,6 @@ By default, the program computes for :math:`\theta` angles in the -70°..+70°
range. This can be changed by using the *angles* keyword.
.. code-block:: python
:linenos:
#For a polar scan between 0° and 60° with 100 points
import numpy as np
@ -201,7 +217,6 @@ work function of the sample, arbitrary set to 4.5 eV.
Of course, you can choose any kinetic energy you'd like:
.. code-block:: python
:linenos:
# To set the kinetic energy...
data = calc.get_theta_scan(level = '2p3/2', kinetic_energy = 300)
@ -209,9 +224,9 @@ Of course, you can choose any kinetic energy you'd like:
Below is the full code of this example. You can download it :download:`here
<Cu_simple.py>`
<Cu.py>`
.. literalinclude:: Cu_simple.py
.. literalinclude:: Cu.py
:linenos:
.. seealso::

View File

@ -15,7 +15,7 @@ orders = (1, 5) # We will run the calculation for single scattering
# and multiple scattering (5th diffusion order)
chain_lengths = (2,3,5) # We will run the calculation for differnt lengths
# of the atomic chain
a = 3.5 # The distance bewteen 2 atoms
a = 3.499 * np.sqrt(2)/2 # The distance bewteen 2 atoms
# Define an empty variable to store all the results
all_data = None
@ -28,11 +28,12 @@ for chain_length in chain_lengths:
chain = Atoms([Atom(symbol, position = (0., 0., i*a)) for i in
range(chain_length)])
# 2- rotating the chain by 45 degrees with respect to the y axis
chain.rotate('y', np.radians(45.))
#chain.rotate('y', np.radians(45.))
chain.rotate(45., 'y')
# 3- setting a custom Muffin-tin radius of 1.5 angstroms for all
# atoms (needed if you want to enlarge the distance between
# the atoms while keeping the radius constant)
[atom.set('mt_radius', 1.5) for atom in chain]
#[atom.set('mt_radius', 1.5) for atom in chain]
# 4- defining the absorber to be the first atom in the chain at
# x = y = z = 0
chain.absorber = 0
@ -43,7 +44,7 @@ for chain_length in chain_lengths:
# Here is how to tweak the scattering order
calc.calculation_parameters.scattering_order = order
# This line below is where we actually run the calculation
all_data = calc.get_theta_scan(level='3s', kinetic_energy=1000.,
all_data = calc.get_theta_scan(level='3s', #kinetic_energy=1000.,
theta=np.arange(0., 80.), data=all_data)
# OPTIONAL, to improve the display of the data we will change the dataset

View File

@ -30,7 +30,7 @@ trajectory for this electron which in turn lowers the signal.
:align: center
:width: 80%
Figure 4. Polar scan of a Ni chain of 2-5 atoms for single and mutliple (5th order)
Figure 1. Polar scan of a Ni chain of 2-5 atoms for single and mutliple (5th order)
scattering.

View File

@ -1,29 +1,34 @@
# coding: utf-8
# coding: utf8
from msspec.calculator import MSSPEC, XRaySource
from msspec.utils import *
from msspec.iodata import Data
from ase.build import bulk
import numpy as np
import sys
a0 = 3.6 # The lattice parameter in angstroms
phi = np.arange(0, 100) # An array of phi angles
all_T = np.arange(300, 1000, 100) # All temperatures used for the calculation
all_theta = np.array([45, 83]) # 2 polar angles, 83° is grazing detection
eps = 0.01 # a useful small value
DATA_FNAME = 'all_data.hdf5' # Where to store all the data
ANALYSIS_FNAME = 'analysis.hdf5'
from msspec.calculator import MSSPEC, XRaySource
from msspec.utils import hemispherical_cluster, get_atom_index
def compute(filename):
"""Will compute a phi scan for an emitter in the first, second and third plane
of a copper substrate for various polar angles and temperatures.
In a second step (outside this function), intensities from all these emitters
are added to get the signal of a substrate."""
calc = MSSPEC(spectroscopy='PED')
def create_clusters(nplanes=3):
copper = bulk('Cu', a=3.6, cubic=True)
clusters = []
for emitter_plane in range(nplanes):
cluster = hemispherical_cluster(copper,
emitter_plane=emitter_plane,
planes=emitter_plane+2,
shape='cylindrical')
cluster.absorber = get_atom_index(cluster, 0, 0, 0)
cluster.info.update({
'emitter_plane': emitter_plane,
})
clusters.append(cluster)
return clusters
def compute(clusters, all_theta=[45., 83.],
all_T=np.arange(300., 1000., 400.)):
data = None
for ic, cluster in enumerate(clusters):
# Retrieve info from cluster object
plane = cluster.info['emitter_plane']
calc = MSSPEC(spectroscopy='PED', algorithm='expansion')
calc.source_parameters.energy = XRaySource.AL_KALPHA
calc.muffintin_parameters.interstitial_potential = 14.1
@ -35,119 +40,90 @@ def compute(filename):
calc.detector_parameters.average_sampling = 'high'
calc.detector_parameters.angular_acceptance = 5.7
for atom in cluster:
atom.set('forward_angle', 30)
atom.set('backward_angle', 30)
filters = ['forward_scattering', 'backward_scattering']
calc.calculation_parameters.path_filtering = filters
calc.calculation_parameters.RA_cutoff = 3
# You can also choose a real potential and manually define the
# electron mean free path
#
# calc.tmatrix_parameters.exchange_correlation = 'hedin_lundqvist_real'
# calc.calculation_parameters.mean_free_path = 10.
data = None # init an empty data object
for temperature in all_T:
for plane in range(3):
# We create a cylindrical cluster here with one plane below the emitter
# and 0, 1 or to planes above the emitter
cluster = bulk('Cu', a=a0, cubic=True)
cluster = cluster.repeat((20, 20, 8))
center_cluster(cluster)
cluster = cut_cylinder(cluster, radius=1.5 * a0 + eps)
cluster = cut_plane(cluster, z=-( a0/2 + eps))
cluster = cut_plane(cluster, z=(plane) * a0 / 2 + eps)
cluster.absorber = get_atom_index(cluster, 0, 0, 0)
calc.calculation_parameters.temperature = temperature
# the scattering order depends on the number of planes above
# the emitter to speed up calculations
calc.calculation_parameters.scattering_order = 1 + plane
calc.calculation_parameters.RA_cutoff = 2
for T in all_T:
for theta in all_theta:
calc.calculation_parameters.temperature = T
calc.calculation_parameters.scattering_order = min(1 + plane, 3)
calc.set_atoms(cluster)
# Here starts the calculation
data = calc.get_phi_scan(level='2p3/2', theta=all_theta, phi=phi,
data = calc.get_phi_scan(level='2p3/2', theta=theta,
phi=np.linspace(0, 100),
kinetic_energy=560, data=data)
dset = data[-1]
dset.title = "plane #{:d}, T={:f}K, theta={:f}°".format(plane,
T,
theta)
data.save(filename)
dset.add_parameter(group='misc', name='plane', value=plane, unit='')
dset.add_parameter(group='misc', name='T', value=T, unit='')
dset.add_parameter(group='misc', name='theta', value=theta, unit='')
return data
def process_data(datafile, outputfile):
"""Will create another Data file with some phi-scans corresponding to 3
planes at different temperatures and the anisotropy curve for 45° and
grazing detection.
"""
def get_signal(datafile, T=300, theta=45):
data = Data.load(datafile)
total = None
def analysis(data):
all_plane = []
all_T = []
all_theta = []
for dset in data:
p = {_['group'] + '.' + _['name']: _['value'] for _ in dset.parameters()}
temperature = np.float(p['CalculationParameters.temperature'])
if temperature != T: continue
i = np.where(dset.plane == -1)
j = np.where(dset.theta[i] == theta)
signal = dset.cross_section[i][j]
try:
total += signal
except:
total = signal
phi = dset.phi[i][j]
return phi, total
plane = dset.get_parameter('misc', 'plane')['value']
T = dset.get_parameter('misc', 'T')['value']
theta = dset.get_parameter('misc', 'theta')['value']
cs = dset.cross_section.copy()
phi = dset.phi.copy()
analysis = Data('Temperature tutorial')
scans_dset = analysis.add_dset('Phi scans')
scans_view = scans_dset.add_view('Figure 1',
title=r'Cu(2p) Azimuthal scan for $\theta = 83\degree$',
xlabel=r'$\Phi (\degree$)',
ylabel='Signal (a.u.)')
anisotropy_dset = analysis.add_dset('Anisotropies')
anisotropy_view = anisotropy_dset.add_view('Figure 2',
if plane not in all_plane: all_plane.append(plane)
if T not in all_T: all_T.append(T)
if theta not in all_theta: all_theta.append(theta)
def get_anisotropy(theta, T):
cs = None
for dset in data:
try:
_T = dset.get_parameter('misc', 'T')['value']
_theta = dset.get_parameter('misc', 'theta')['value']
_cs = dset.cross_section.copy()
phi = dset.phi.copy()
except:
continue
if _theta == theta and _T == T:
try:
cs += _cs
except:
cs = _cs
Imax = np.max(cs)
Imin = np.min(cs)
return (Imax - Imin)/Imax
# create a substrate dataset for each T and theta
anisotropy_dset = data.add_dset("all")
anisotropy_view = anisotropy_dset.add_view('Anisotropies',
title='Relative anisotropies for Cu(2p)',
marker='o',
xlabel='T (K)',
ylabel=r'$\frac{\Delta I / I_{max}(T)}{\Delta I_{300} / I_{max}(300)} (\%)$')
ylabel=r'$\frac{\Delta I / I_{max}(T)}{\Delta I_{300}'
r'/ I_{max}(300)} (\%)$')
for theta in all_theta:
for T in all_T:
PHI, SIGNAL = get_signal(datafile, T=T, theta=theta)
for phi, signal in zip(PHI, SIGNAL):
scans_dset.add_row(phi=phi, signal=signal, theta=theta, temperature=T)
A = get_anisotropy(theta, T)
A0 = get_anisotropy(theta, np.min(all_T))
middleT = all_T[np.abs(all_T - np.mean(all_T)).argmin()]
if theta == 83 and T in [np.min(all_T), middleT, np.max(all_T)]:
scans_view.select('phi', 'signal',
where='temperature == {:f} and theta == {:f}'.format(T, theta),
legend='{:.0f} K'.format(T))
PHI, SIGNAL0 = get_signal(datafile, T=np.min(all_T), theta=theta)
Imax = np.max(SIGNAL)
Imax0 = np.max(SIGNAL0)
dI = Imax - np.min(SIGNAL)
dI0 = Imax0 - np.min(SIGNAL0)
ani = (dI / Imax) / (dI0 / Imax0)
anisotropy_dset.add_row(temperature=T, anisotropy=ani, theta=theta)
anisotropy_dset.add_row(temperature=T, theta=theta, anisotropy=A/A0)
anisotropy_view.select('temperature', 'anisotropy',
where='theta == {:f}'.format(theta),
legend=r'$\theta = {:.0f} \degree$'.format(theta))
analysis.save(outputfile)
# A convenient way to run the script, just specify one or more of these calc, analyse or
# view keywords as arguments
# ... to calculate all the data, analyse the data and view the results, run
# python Cu_temperature.py calc analyse view
# ... to just view the results, simply run
# python Cu_temperature.py view
if 'calc' in sys.argv:
compute(DATA_FNAME)
if 'analyse' in sys.argv:
process_data(DATA_FNAME, ANALYSIS_FNAME)
if 'view' in sys.argv:
data = Data.load(ANALYSIS_FNAME)
data.view()
return data
clusters = create_clusters()
data = compute(clusters)
data = analysis(data)
data.view()

View File

@ -12,7 +12,7 @@ if ! [ -d "$VENV_PATH" ]; then
fi
launch_script() {
. "$VENV_PATH/bin/activate" && python $@
. "$VENV_PATH/bin/activate" && python "$@"
}
show_help () {

View File

@ -747,15 +747,30 @@ class _PED(_MSCALCULATOR):
proto_index = i+1
title = 'Scattering factor at {:.3f} eV'.format(kinetic_energy)
mini = min(map(np.min, [dset.sf_real, dset.sf_imag, dset.sf_module]))
maxi = max(map(np.max, [dset.sf_real, dset.sf_imag, dset.sf_module]))
view = dset.add_view("Proto. atom #{:d}".format(proto_index),
title=title, projection='polar')
title=title, projection='polar',
ylim=[mini, maxi])
where = "proto_index=={:d}".format(proto_index)
view.select('theta', 'sf_module', where=where,
legend=r'$|f(\theta)|$')
view.select('theta', 'sf_real', where=where,
legend=r'$\Im(f(\theta))$')
view.select('theta', 'sf_imag', where=where,
legend=r'$\Re(f(\theta))$')
view.select('theta', 'sf_imag', where=where,
legend=r'$\Im(f(\theta))$')
if scan_type == 'energy':
absorber_symbol = self.atoms[self.atoms.absorber].symbol
title = (r'Energy scan of {}({}) at $\theta$={:.2f}$\degree$ and '
'$\phi$={:.2f}$\degree$').format(
absorber_symbol, level, theta, phi)
xlabel = r'Photoelectron kinetic energy (eV)'
ylabel = r'Signal (a. u.)'
view = dset.add_view("EnergyScan".format(ke), title=title,
xlabel=xlabel, ylabel=ylabel)
view.select('energy', 'cross_section')
# save the cluster
#clusbuf = StringIO()
@ -922,6 +937,27 @@ class _PED(_MSCALCULATOR):
malloc={'NPH_M': 8000})
return data
def get_energy_scan(self, phi=0, theta=0,
level=None, kinetic_energy=None, data=None):
"""Computes an energy scan of the emitted photoelectrons.
:param phi: All the values of the azimuthal angle to be computed. See
:ref:`scanparameters-phi`.
:param theta: The polar angle in degrees. See
:ref:`scanparameters-theta`.
:param level: The electronic level. See :ref:`pedparameters-level`.
:param kinetic_energy: see :ref:`scanparameters-kinetic_energy`.
:param data: a :py:class:`iodata.Data` object to append the results to
or None.
:returns: The modified :py:class:`iodata.Data` object passed as an
argument or a new :py:class:`iodata.Data` object.
"""
data = self._get_scan(scan_type='energy', level=level, theta=theta,
phi=phi, kinetic_energy=kinetic_energy, data=data)
return data
class _EIG(_MSCALCULATOR):
"""

View File

@ -12,7 +12,6 @@ import pandas as pd
import time
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
@ -236,7 +235,22 @@ class Looper:
df = pd.DataFrame(dfdata, columns=columns)
self.data = df
return df
#return df
# return a list of [x0, y0, x1, y1,...xn, yn] and a list
# of corresponding dict of parameters {'keyA': [val0,...valn],
# 'keyB': [val0,...valn], ...}
all_xy = []
for irow, row in df.iterrows():
all_xy.append(row.output[0])
all_xy.append(row.output[1])
parameters = df.to_dict()
parameters.pop('output')
return all_xy, parameters
@ -282,7 +296,7 @@ if __name__ == "__main__":
looper = Looper()
looper.pipeline = bar
data = looper.run(emitter, emitter_plane, uij, theta, levels, ncpu=1,
data = looper.run(emitter, emitter_plane, uij, theta, levels, ncpu=4,
passindex=True)
print(data[data.emitter_plane.eq(0)].theta.unique())
print(data)
#print(data[data.emitter_plane.eq(0)].theta.unique())

View File

@ -853,8 +853,8 @@ class MuffintinParameters(BaseParameters):
def __init__(self, phagen_parameters, spec_parameters):
parameters = (
Parameter('charge_relaxation', types=bool, default=True, doc="""
Used to specify wether the charge density of the photoabsorbing atom, which is used
to construct the potential, is allowaed to relax around the core hole or not.
Used to specify whether the charge density of the photoabsorbing atom, which is used
to construct the potential, is allowed to relax around the core hole or not.
"""),
Parameter('ionicity', types=dict, default={}, doc="""
A dictionary to specify the ionicity of each kind of atoms. If empty, the atoms are considered to be

View File

@ -17,7 +17,7 @@ c
c Local variables
c
integer :: lwork
complex*16 :: wquery
complex*16 :: wquery(1)
complex*16 :: vl(1,1), vr(1,1)
c
real*8, allocatable :: rwork(:)
@ -39,7 +39,7 @@ c
write(iuo1,*) ' '
end if
c
lwork = int(wquery)
lwork = int(wquery(1))
allocate(work(lwork))
c
call zgeev('n','n',n,a,lda,w,vl,1,vr,1,work,lwork,rwork,info)

View File

@ -113,7 +113,7 @@ C
CST PROGRAM COMP_CURVE
SUBROUTINE COMP_CURVES()
C
PARAMETER (N_SIZE=1000,N_FILES=100,NMAX=9999)
PARAMETER (N_SIZE=1000,N_FILES=1000,NMAX=9999)
C
INTEGER CC_EXP(N_SIZE),CC_CAL(N_SIZE),VALUE,NVALUE
C
@ -1634,7 +1634,7 @@ C Author : D. Sébilleau
C
C Last modified : 9 Sep 2014
C
PARAMETER (N_SIZE=1000,N_FILES=100)
PARAMETER (N_SIZE=1000,N_FILES=1000)
C
REAL*4 X_CAL(N_SIZE),I_CAL,X,Y
REAL*4 DIFF,STEP1,STEP2
@ -2955,7 +2955,7 @@ C Author : D. Sébilleau
C
C Last modified : 5 Sep 2014
C
PARAMETER (N_SIZE=1000,N_FILES=100)
PARAMETER (N_SIZE=1000,N_FILES=1000)
C
REAL*4 EXPE(N_SIZE),CALCULATION(N_SIZE,N_FILES)
REAL*4 MIN_EXP,MIN_CAL,MINIMUM,SHIFT
@ -9748,7 +9748,7 @@ C Author : D. Sébilleau
C
C Last modified : 19 Aug 2014
C
PARAMETER (N_SIZE=1000,N_FILES=100)
PARAMETER (N_SIZE=1000,N_FILES=1000)
C
REAL*4 EXPE(N_SIZE),CALC(N_SIZE),Y_MEAN(N_SIZE)
real*4 x(N_SIZE)

View File

@ -3,7 +3,7 @@ PYMAJ = 3
PYMIN = 6
FC = gfortran
F2PY = f2py3
F2PY = f2py3 --f77exec=$(FC) --f90exec=$(FC)
NO_VENV = 0
DEBUG = 0

View File

@ -5,6 +5,7 @@ lxml
matplotlib
numpy
Pint
pandas
pycairo
scipy
setuptools-scm

View File

@ -0,0 +1,163 @@
#!/usr/bin/env bash
#
# Copyright © 2016-2021 - Rennes Physics Institute
#
# This file is part of msspec.
#
# msspec is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# msspec is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this msspec. If not, see <http://www.gnu.org/licenses/>.
#
# Source file : utils/dockerized/linux/msspec
# Last modified: Thu, 23 Sep 2021 16:55:16 +0200
# Committed by : sylvain tricot <sylvain.tricot@univ-rennes1.fr>
THIS_SCRIPT="$0"
IMAGE_NAME="iprcnrs/msspec:latest"
Logln () {
echo "$1" >&2
}
Log () {
echo -n "$1" >&2
}
Read_YesNo () {
PROMPT="$1"
DEFAULT="$2"
ANSWER=""
RESPONSE=""
VALID=1
while test $VALID -ne 0; do
read -p "${PROMPT} (y/n) [${DEFAULT}]? " "RESPONSE"
ANSWER="${RESPONSE:-${DEFAULT}}"
case "${ANSWER}" in
y|n) VALID=0 ;;
*) echo "Invalid choice, please answer \"y\" or \"n\"."; VALID=1 ;;
esac
done
}
Get_MsSpecContainerID () {
CID=$(docker ps -a -q --filter ancestor=$IMAGE_NAME)
echo $CID
}
Get_MsSpecImageID () {
IID=$(docker images -q $IMAGE_NAME)
echo $IID
}
Add_MsSpecImage () {
docker pull $IMAGE_NAME 1>&2
}
Add_MsSpecContainer () {
CID=$(Get_MsSpecContainerID)
if [ -z "$CID" ]; then
IID=$(Get_MsSpecImageID)
if [ -z "$IID" ]; then
Logln "Pulling MsSpec image..."
Add_MsSpecImage
fi
Log "Creating the MsSpec container... "
USERNAME=$(whoami)
USERID=$(id -u $USERNAME)
GROUPID=$(id -g $USERNAME)
CID=$(docker create -i --net=host -e DISPLAY=$DISPLAY -v $HOME:$HOME -u ${USERID}:${GROUPID} --entrypoint /bin/bash $IMAGE_NAME)
Logln "done."
fi
echo $CID
}
Start_MsSpecContainer () {
CID=$(Add_MsSpecContainer)
status=$(docker container inspect -f '{{.State.Status}}' $CID)
if [ $status != "running" ]; then
Log "Starting MsSpec container... "
# Start the container
CID=$(docker start $CID)
Logln "done."
fi
}
Remove_MsSpecContainer () {
Log "Removing MsSpec container... "
CID=$(Get_MsSpecContainerID)
docker stop -t 1 $CID >/dev/null 2>&1
docker rm $CID >/dev/null 2>&1
Logln "done."
}
Run_MsSpec () {
# Run msspec command
CID=$(Get_MsSpecContainerID)
xhost +localhost >/dev/null 2>&1
docker exec -i -t -w "$PWD" $CID msspec "$@"
}
Run_Bash () {
# Run msspec command
CID=$(Get_MsSpecContainerID)
xhost +localhost >/dev/null 2>&1
docker exec -i -t -w "$PWD" -e HOME=$HOME -e PS1="MsSpec:\w> " $CID /bin/bash --norc --noprofile
}
Uninstall_MsSpecImage () {
Read_YesNo "You are about to remove the MsSpec Docker image, its container and this script. Are you sure" "n"
case $ANSWER in
y) Remove_MsSpecContainer;
Log "Removing ${IMAGE_NAME}...";
docker rmi $IMAGE_NAME >/dev/null 2>&1;
Logln "done.";
Log "Removing ${THIS_SCRIPT}...";
rm -f $THIS_SCRIPT;
Logln "done.";
;;
n) echo "Uninstallation aborted."
esac
}
Show_Help () {
echo "Usage: 1) msspec -p [PYTHON OPTIONS] SCRIPT [ARGUMENTS...]"
echo " 2) msspec [-l FILE | -i | -h]"
echo " 3) msspec [bash | reset]"
echo ""
echo "Form (1) is used to launch a script"
echo "Form (2) is used to load a hdf5 data file"
echo "Form (3) is used to control the Docker container/image."
echo ""
echo "List of possible options:"
echo " -p Pass every arguments after this option to the msspec"
echo " virtual environment Python interpreter."
echo " -i Run the interactive Python interpreter within msspec"
echo " virtual environment."
echo " -l Load and display a *.hdf5 data file in a graphical"
echo " window."
echo " -v Print the version."
echo " -h Show this help message."
echo ""
echo " bash This command starts an interactive bash shell in the"
echo " MsSpec container."
echo " reset This command removes the MsSpec container (but not the"
echo " image). Changes made in the container will be lost and"
echo " any new call to msspec will recreate a new fresh container."
}
case $1 in
reset) Remove_MsSpecContainer ;;
bash) Start_MsSpecContainer; Run_Bash ;;
"-u") Uninstall_MsSpecImage ;;
"-h"|"") Start_MsSpecContainer; Show_Help ;;
*) Start_MsSpecContainer; Run_MsSpec "$@" ;;
esac

View File

@ -0,0 +1,219 @@
// ----------------------------------------------------------------------------
//
// Inno Setup Ver: 5.4.2
// Script Version: 1.4.2
// Author: Jared Breland <jbreland@legroom.net>
// Homepage: http://www.legroom.net/software
// License: GNU Lesser General Public License (LGPL), version 3
// http://www.gnu.org/licenses/lgpl.html
//
// Script Function:
// Allow modification of environmental path directly from Inno Setup installers
//
// Instructions:
// Copy modpath.iss to the same directory as your setup script
//
// Add this statement to your [Setup] section
// ChangesEnvironment=true
//
// Add this statement to your [Tasks] section
// You can change the Description or Flags
// You can change the Name, but it must match the ModPathName setting below
// Name: modifypath; Description: &Add application directory to your environmental path; Flags: unchecked
//
// Add the following to the end of your [Code] section
// ModPathName defines the name of the task defined above
// ModPathType defines whether the 'user' or 'system' path will be modified;
// this will default to user if anything other than system is set
// setArrayLength must specify the total number of dirs to be added
// Result[0] contains first directory, Result[1] contains second, etc.
// const
// ModPathName = 'modifypath';
// ModPathType = 'user';
//
// function ModPathDir(): TArrayOfString;
// begin
// setArrayLength(Result, 1);
// Result[0] := ExpandConstant('{app}');
// end;
// #include "modpath.iss"
// ----------------------------------------------------------------------------
procedure ModPath();
var
oldpath: String;
newpath: String;
updatepath: Boolean;
pathArr: TArrayOfString;
aExecFile: String;
aExecArr: TArrayOfString;
i, d: Integer;
pathdir: TArrayOfString;
regroot: Integer;
regpath: String;
begin
// Get constants from main script and adjust behavior accordingly
// ModPathType MUST be 'system' or 'user'; force 'user' if invalid
if ModPathType = 'system' then begin
regroot := HKEY_LOCAL_MACHINE;
regpath := 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
end else begin
regroot := HKEY_CURRENT_USER;
regpath := 'Environment';
end;
// Get array of new directories and act on each individually
pathdir := ModPathDir();
for d := 0 to GetArrayLength(pathdir)-1 do begin
updatepath := true;
// Modify WinNT path
if UsingWinNT() = true then begin
// Get current path, split into an array
RegQueryStringValue(regroot, regpath, 'Path', oldpath);
oldpath := oldpath + ';';
i := 0;
while (Pos(';', oldpath) > 0) do begin
SetArrayLength(pathArr, i+1);
pathArr[i] := Copy(oldpath, 0, Pos(';', oldpath)-1);
oldpath := Copy(oldpath, Pos(';', oldpath)+1, Length(oldpath));
i := i + 1;
// Check if current directory matches app dir
if pathdir[d] = pathArr[i-1] then begin
// if uninstalling, remove dir from path
if IsUninstaller() = true then begin
continue;
// if installing, flag that dir already exists in path
end else begin
updatepath := false;
end;
end;
// Add current directory to new path
if i = 1 then begin
newpath := pathArr[i-1];
end else begin
newpath := newpath + ';' + pathArr[i-1];
end;
end;
// Append app dir to path if not already included
if (IsUninstaller() = false) AND (updatepath = true) then
newpath := newpath + ';' + pathdir[d];
// Write new path
RegWriteStringValue(regroot, regpath, 'Path', newpath);
// Modify Win9x path
end else begin
// Convert to shortened dirname
pathdir[d] := GetShortName(pathdir[d]);
// If autoexec.bat exists, check if app dir already exists in path
aExecFile := 'C:\AUTOEXEC.BAT';
if FileExists(aExecFile) then begin
LoadStringsFromFile(aExecFile, aExecArr);
for i := 0 to GetArrayLength(aExecArr)-1 do begin
if IsUninstaller() = false then begin
// If app dir already exists while installing, skip add
if (Pos(pathdir[d], aExecArr[i]) > 0) then
updatepath := false;
break;
end else begin
// If app dir exists and = what we originally set, then delete at uninstall
if aExecArr[i] = 'SET PATH=%PATH%;' + pathdir[d] then
aExecArr[i] := '';
end;
end;
end;
// If app dir not found, or autoexec.bat didn't exist, then (create and) append to current path
if (IsUninstaller() = false) AND (updatepath = true) then begin
SaveStringToFile(aExecFile, #13#10 + 'SET PATH=%PATH%;' + pathdir[d], True);
// If uninstalling, write the full autoexec out
end else begin
SaveStringsToFile(aExecFile, aExecArr, False);
end;
end;
end;
end;
// Split a string into an array using passed delimeter
procedure MPExplode(var Dest: TArrayOfString; Text: String; Separator: String);
var
i: Integer;
begin
i := 0;
repeat
SetArrayLength(Dest, i+1);
if Pos(Separator,Text) > 0 then begin
Dest[i] := Copy(Text, 1, Pos(Separator, Text)-1);
Text := Copy(Text, Pos(Separator,Text) + Length(Separator), Length(Text));
i := i + 1;
end else begin
Dest[i] := Text;
Text := '';
end;
until Length(Text)=0;
end;
procedure CurStepChanged(CurStep: TSetupStep);
var
taskname: String;
begin
taskname := ModPathName;
if CurStep = ssPostInstall then
if WizardIsTaskSelected(taskname) then
ModPath();
end;
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var
aSelectedTasks: TArrayOfString;
i: Integer;
taskname: String;
regpath: String;
regstring: String;
appid: String;
begin
// only run during actual uninstall
if CurUninstallStep = usUninstall then begin
// get list of selected tasks saved in registry at install time
appid := '{#emit SetupSetting("AppId")}';
if appid = '' then appid := '{#emit SetupSetting("AppName")}';
regpath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\'+appid+'_is1');
RegQueryStringValue(HKLM, regpath, 'Inno Setup: Selected Tasks', regstring);
if regstring = '' then RegQueryStringValue(HKCU, regpath, 'Inno Setup: Selected Tasks', regstring);
// check each task; if matches modpath taskname, trigger patch removal
if regstring <> '' then begin
taskname := ModPathName;
MPExplode(aSelectedTasks, regstring, ',');
if GetArrayLength(aSelectedTasks) > 0 then begin
for i := 0 to GetArrayLength(aSelectedTasks)-1 do begin
if comparetext(aSelectedTasks[i], taskname) = 0 then
ModPath();
end;
end;
end;
end;
end;
function NeedRestart(): Boolean;
var
taskname: String;
begin
taskname := ModPathName;
if WizardIsTaskSelected(taskname) and not UsingWinNT() then begin
Result := True;
end else begin
Result := False;
end;
end;

Binary file not shown.

View File

@ -0,0 +1,69 @@
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppName "MsSpec"
#define MyAppVersion ""
#define MyAppPublisher "IPR"
#define MyAppURL "https://msspec.cnrs.fr"
#define MyAppExeName "msspec.exe"
#define MyAppInstallerName "msspec_setup"
[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{BB2F7A31-BDDF-4D22-BDBD-C77BEB6D3780}}
AppName={#MyAppName}
;AppVersion={#MyAppVersion}
AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={autopf}\{#MyAppName}
DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes
; Uncomment the following line to run in non administrative install mode (install for current user only.)
;PrivilegesRequired=lowest
PrivilegesRequiredOverridesAllowed=dialog
OutputBaseFilename={#MyAppInstallerName}
Compression=lzma
SolidCompression=yes
WizardStyle=modern
ChangesEnvironment=true
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Files]
Source: ".\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
;Source: "D:\Home\stricot\Documents\WindowsPowerShell\Scripts\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
;[Icons]
;Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
;[Run]
;Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
[Tasks]
Name: modifypath; Description: Add application directory to your environmental path;
;Flags: unchecked
[UninstallRun]
Filename: "{app}\{#MyAppExeName}"; Parameters: "-u";
[Messages]
FinishedLabelNoIcons=Setup has finished installing [name] on your computer. To launch MsSpec, open a terminal window and enter 'msspec'.
[Code]
const
ModPathName = 'modifypath';
ModPathType = 'user';
function ModPathDir(): TArrayOfString;
begin
setArrayLength(Result, 1)
Result[0] := ExpandConstant('{app}');
end;
#include "modpath.iss"

View File

@ -0,0 +1,171 @@
##[Ps1 To Exe]
##
##Kd3HDZOFADWE8uK1
##Nc3NCtDXThU=
##Kd3HFJGZHWLWoLaVvnQnhQ==
##LM/RF4eFHHGZ7/K1
##K8rLFtDXTiW5
##OsHQCZGeTiiZ4tI=
##OcrLFtDXTiW5
##LM/BD5WYTiiZ4tI=
##McvWDJ+OTiiZ4tI=
##OMvOC56PFnzN8u+Vs1Q=
##M9jHFoeYB2Hc8u+Vs1Q=
##PdrWFpmIG2HcofKIo2QX
##OMfRFJyLFzWE8uK1
##KsfMAp/KUzWJ0g==
##OsfOAYaPHGbQvbyVvnQX
##LNzNAIWJGmPcoKHc7Do3uAuO
##LNzNAIWJGnvYv7eVvnQX
##M9zLA5mED3nfu77Q7TV64AuzAgg=
##NcDWAYKED3nfu77Q7TV64AuzAgg=
##OMvRB4KDHmHQvbyVvnQX
##P8HPFJGEFzWE8tI=
##KNzDAJWHD2fS8u+Vgw==
##P8HSHYKDCX3N8u+Vgw==
##LNzLEpGeC3fMu77Ro2k3hQ==
##L97HB5mLAnfMu77Ro2k3hQ==
##P8HPCZWEGmaZ7/K1
##L8/UAdDXTlGDjpra7jFL9l/8S2skevm/trWyyYSy6/nQjCzXTZUDWmR4gSzuN0O4Vf4uZvYHvcEFRiEnPOEb57GeHv+sJQ==
##Kc/BRM3KXhU=
##
##
##fd6a9f26a06ea3bc99616d4851b372ba
# PowerShell
$SCRIPT_PATH = $MyInvocation.MyCommand.Path
$IMAGE_NAME = "iprcnrs/msspec:latest"
Function Read-YesNo($PROMPT, $DEFAULT) {
$VALID = 1
While($VALID -ne 0) {
$ANSWER = Read-Host "$PROMPT (y/n) [$DEFAULT]? "
Switch($ANSWER) {
"" {$ANSWER=$DEFAULT; $VALID=0; Break}
"y" {$VALID=0; Break}
"n" {$VALID=0; Break}
Default {Write-Host "Invalid choice, please answer 'y' or 'n'."; $VALID=1; Break}
}
}
Return $ANSWER
}
Function Get-MsSpecContainerID {
Return docker ps -a -q --filter ancestor=$IMAGE_NAME
}
Function Get-MsSpecImageID {
Return docker images -q $IMAGE_NAME
}
Function Add-MsSpecImage {
Write-Host "Pulling MsSpec image...";
docker pull $IMAGE_NAME;
Write-Host "done."
$IID = Get-MsSpecImageID;
Return $IID;
}
Function Add-MsSpecContainer {
$CID = Get-MsSpecContainerID
If($CID -eq $NULL) {
$IID = Get-MsSpecImageID
If($IID -eq $NULL) {
#Add-MsSpecImage;
}
Write-Host -nonewline "Creating the MsSpec container... "
$mydocuments = [environment]::GetFolderPath("mydocuments")
$drive = ($mydocuments -split ":",2)[0]
docker create -i -v ${drive}:\:/$drive --entrypoint /bin/bash $IMAGE_NAME >$NULL
$CID = Get-MsSpecContainerID
Write-Host "done."
}
Return $CID
}
Function Start-MsSpecContainer {
$CID = Add-MsSpecContainer;
$status = docker container inspect -f '{{.State.Status}}' $CID;
IF($status -ne "running") {
Write-Host -nonewline "Starting MsSpec container...";
$CID = docker start $CID;
Write-Host "done.";
}
}
Function Remove-MsSpecContainer {
Write-Host -nonewline "Removing MsSpec container...";
$CID = Get-MsSpecContainerID;
IF($CID -ne $NULL) {
docker stop -t 1 $CID >$NULL;
docker rm $CID >$NULL;
}
Write-Host "done."
}
Function Run-MsSpec($opts) {
# Run msspec command
$CID = Get-MsSpecContainerID;
$nixPath = "/" + (${PWD} -replace "\\","/") -replace ":",""
docker exec -i -t -e DISPLAY=host.docker.internal:0 -w $nixPath $CID msspec $opts
}
Function Run-Bash {
# Run bash
$CID = Get-MsSpecContainerID;
$nixPath = "/" + (${PWD} -replace "\\","/") -replace ":",""
docker exec -i -t -w $nixPath -e DISPLAY=host.docker.internal:0 $CID /bin/bash
}
Function Uninstall-MsSpecImage {
$ANSWER = Read-YesNo "You are about to remove the MsSpec Docker image, its container and this script. Are you sure" "n"
Switch($ANSWER) {
"y" {Remove-MsSpecContainer;
Write-Host -nonewline "Removing $IMAGE_NAME...";
$IID = Get-MsSpecImageID;
If($IID -ne $NULL) {
docker rmi $IMAGE_NAME >$NULL;
}
Write-Host "done.";
# Remove-Item $THIS_SCRIPT;
Break;
}
"n" {Write-Host "Uninstallation aborted."; Break}
}
}
Function Show-Help {
Write-Host "Usage: 1) msspec -p [PYTHON OPTIONS] SCRIPT [ARGUMENTS...]"
Write-Host " 2) msspec [-l FILE | -i | -h]"
Write-Host " 3) msspec [bash | reset]"
Write-Host ""
Write-Host "Form (1) is used to launch a script"
Write-Host "Form (2) is used to load a hdf5 data file"
Write-Host "Form (3) is used to control the Docker container/image."
Write-Host ""
Write-Host "List of possible options:"
Write-Host " -p Pass every arguments after this option to the msspec"
Write-Host " virtual environment Python interpreter."
Write-Host " -i Run the interactive Python interpreter within msspec"
Write-Host " virtual environment."
Write-Host " -l Load and display a *.hdf5 data file in a graphical"
Write-Host " window."
Write-Host " -v Print the version."
Write-Host " -h Show this help message."
Write-Host ""
Write-Host " bash This command starts an interactive bash shell in the"
Write-Host " MsSpec container."
Write-Host " reset This command removes the MsSpec container (but not the"
Write-Host " image). Changes made in the container will be lost and"
Write-Host " any new call to msspec will recreate a new fresh container."
}
Switch($args[0]) {
"reset" {Remove-MsSpecContainer; Break}
"bash" {Start-MsSpecContainer; Run-Bash; Break}
"-u" {Uninstall-MsSpecImage; Break}
"-h" {Start-MsSpecContainer; Show-Help; Break}
"" {Start-MsSpecContainer; Show-Help; Break}
Default {Start-MsSpecContainer; Run-MsSpec $args; Break}
pull {Add-MsSpecImage; Break}
}

Binary file not shown.