Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/1313e/PRISM
Browse files Browse the repository at this point in the history
  • Loading branch information
1313e committed Oct 2, 2020
2 parents 3e89764 + 6b74f8d commit e6c0a50
Show file tree
Hide file tree
Showing 31 changed files with 1,093 additions and 785 deletions.
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,13 @@ And, finally, if you use *PRISM* as part of your workflow in a scientific public

Acknowledgements
================
Special thanks to Alan Duffy, Darren Croton, Simon Mutch and Manodeep Sinha for providing many valuable suggestions and constructive feedback points.
Special thanks to Darren Croton, Alan Duffy, Michael Goldstein, Simon Mutch, Manodeep Sinha and Ian Vernon for providing many valuable suggestions and constructive feedback points.
Huge thanks to James Josephides for making the *PRISM* logo.

.. |PyPI| image:: https://img.shields.io/pypi/v/prism.svg?logo=pypi&logoColor=white&label=PyPI
:target: https://pypi.python.org/pypi/prism
:alt: PyPI - Latest Release
.. |Python| image:: https://img.shields.io/pypi/pyversions/prism.svg?logo=python&logoColor=white&label=Python
.. |Python| image:: https://img.shields.io/badge/Python-3.5%2B-blue?logo=python&logoColor=white
:target: https://pypi.python.org/pypi/prism
:alt: PyPI - Python Versions
.. |Azure| image:: https://img.shields.io/azure-devops/build/1313e/2f7c67c7-61eb-4e70-9ff3-7f54f8e39987/1?logo=azure-pipelines&logoColor=white&label=Azure
Expand Down
1 change: 1 addition & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
'matplotlib': ('https://matplotlib.org', None),
'h5py': ('https://h5py.readthedocs.io/en/stable', None),
'e13tools': ('https://e13tools.readthedocs.io', None),
'cmasher': ('https://cmasher.readthedocs.io', None),
'PyQt5': ('https://www.riverbankcomputing.com/static/Docs/PyQt5', None)}

# Autodoc configuration
Expand Down
5 changes: 4 additions & 1 deletion docs/source/user/call_model.inc
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ Input arguments
###############
Depending on the values of the :attr:`~prism.modellink.ModelLink.multi_call` and :attr:`~prism.modellink.ModelLink.MPI_call` flags (where the first is set by the :attr:`~prism.modellink.ModelLink.call_type` flag), the :obj:`~prism.Pipeline` instance will use the :meth:`~prism.modellink.ModelLink.call_model` method differently.
As explained in :ref:`writing_modellink`, every model evaluation sample is requested individually in serial by default, which corresponds to :attr:`~prism.modellink.ModelLink.multi_call` is :pycode:`False` and :attr:`~prism.modellink.ModelLink.MPI_call` is :pycode:`False`.
When single-calling a model, *PRISM* expects an array-like container back with shape :pycode:`(n_data)`, where the order of the elements is the same as the order of the requested :pycode:`data_idx`.
When single-calling a model, *PRISM* expects an array-like container back with shape :pycode:`(n_data,)`, where the order of the elements is the same as the order of the requested :pycode:`data_idx`.
If we assume that we have an instance of the :class:`LineLink` class (introduced in `line_link.py`_) called :pycode:`modellink_obj` and want to evaluate the model three times for all data points, then the model would be called as (solely by the controller rank)::

# Import SortedDict class
from sortedcontainers import SortedDict as sdict

# Get emul_i, sam_set and data_idx
emul_i = 1
sam_set = np.random.rand(3, modellink_obj.n_par)
Expand Down
2 changes: 1 addition & 1 deletion docs/source/user/hybrid_sampling.inc
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ For this, we need to define an `lnpost()` function, for which we will use a simp
data_var = [err[0]**2 for err in pipe.modellink.data_err]

# Calculate the posterior probability and return it
sigma_2 = md_var+data_var
sigma2 = md_var+data_var
diff = pipe.modellink.data_val-mod_out
return(-0.5*(np.sum(diff**2/sigma2)))

Expand Down
11 changes: 9 additions & 2 deletions docs/source/user/projections.inc
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,22 @@ It should therefore only be used when necessary.
If :pycode:`False`, only the parameter space in which the emulator is defined is shown, which more often than not allows for more details to be seen in the projection figure.
If :pycode:`True`, the full model parameter space is used for the axes limits, allowing projection figures from different iterations to be compared with each other more easily.

.. versionadded:: 1.2.4
The `full_impl_rng` argument is a bool, which controls whether the lower limit for the minimum implausibility plot should be set to zero (:pycode:`True`) or to the lowest implausibility value plotted (:pycode:`False`), with the latter being the default.
If :pycode:`False`, only the implausibility range in which plausible samples are plotted will be used, which increases the amount of detail in the minimum implausibility plot.
If :pycode:`True`, the entire implausibility range that can hold plausible samples is used, allowing for the relative implausibility difference between samples to be interpreted correctly.
Set this value to :pycode:`True` if one wishes to have the same plotting behavior as in versions earlier than v1.2.4.

The `force` argument is a bool, which controls what to do if a projection is requested for which data already exists.
If :pycode:`False` (default), it will use the previously acquired projection data to create the projection figure if it does not exist, skip if it does or return the figure data if `figure` is :pycode:`False`.
If :pycode:`True`, the projection data and all associated projection figures will be deleted, and the projection will be recalculated.

The remaining seven arguments are keyword argument dicts, that need to be passed to the various different plotting functions that are used for creating the projection figures.
The remaining eight arguments are keyword argument dicts, that need to be passed to the various different plotting functions that are used for creating the projection figures.
The `fig_kwargs` dict is passed to the :func:`~matplotlib.pyplot.figure` function when creating the projection figure instance.
The `impl_kwargs_2D` and `los_kwargs_2D` dicts are passed to the :func:`~matplotlib.pyplot.plot` function when making the minimum implausibility and line-of-sight depth subplots, respectively, for the 2D projections.
Similarly, the `impl_kwargs_3D` and `los_kwargs_3D` dicts are passed to the :func:`~matplotlib.pyplot.hexbin` function for 3D projections.
And, finally, the `line_kwargs_est` and `line_kwargs_cut` dicts are passed to the :func:`~matplotlib.pyplot.draw` function for drawing the parameter estimate and implausibility cut-off lines.
The `line_kwargs_est` and `line_kwargs_cut` dicts are passed to the :func:`~matplotlib.pyplot.draw` function for drawing the parameter estimate and implausibility cut-off lines.
And, finally, the `arrow_kwargs_est` dict is passed to the :func:`~matplotlib.pyplot.arrow` function for drawing the parameter estimate arrow in case its line is out-of-range.

Crystal (GUI)
#############
Expand Down
4 changes: 2 additions & 2 deletions prism/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

# %% VERSIONS
# Default/Latest/Current version
__version__ = '1.2.3'
__version__ = '1.3.1'

# Compatibility versions
compat_version = ['1.0.0rc12']
compat_version = ['1.0.0rc12', '1.2.2']
6 changes: 5 additions & 1 deletion prism/_gui/widgets/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from os import path

# Package imports
from qtpy import QtWidgets as QW
from qtpy import QtCore as QC, QtWidgets as QW
import pytest

# PRISM imports
Expand All @@ -14,6 +14,10 @@
from prism.modellink.tests.modellink import GaussianLink3D


# Set the default Locale to English
QC.QLocale.setDefault(QC.QLocale(31))


# %% GLOBALS
DIR_PATH = path.abspath(path.dirname(__file__)) # Path to tests directory

Expand Down
111 changes: 5 additions & 106 deletions prism/_gui/widgets/preferences/custom_boxes.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import e13tools as e13
from matplotlib import cm, rcParams
from matplotlib.colors import BASE_COLORS, CSS4_COLORS, to_rgba
import matplotlib.pyplot as plt
import numpy as np
from qtpy import QtCore as QC, QtGui as QG, QtWidgets as QW
from sortedcontainers import SortedDict as sdict, SortedSet as sset
Expand All @@ -31,7 +32,7 @@
QW_QSpinBox, get_box_value, set_box_value)

# All declaration
__all__ = ['ColorBox', 'ColorMapBox', 'DefaultBox', 'FigSizeBox']
__all__ = ['ColorBox', 'ColorMapBox', 'DefaultBox']


# %% CLASS DEFINITIONS
Expand Down Expand Up @@ -455,9 +456,10 @@ def init(self):
std_cmaps_r = sset([cmap+'_r' for cmap in std_cmaps])

# Obtain a list with all colormaps and their reverses
all_cmaps = sset([cmap for cmap in cm.cmap_d
all_cmaps = sset([cmap for cmap in plt.colormaps()
if not cmap.endswith('_r')])
all_cmaps_r = sset([cmap for cmap in cm.cmap_d if cmap.endswith('_r')])
all_cmaps_r = sset([cmap for cmap in plt.colormaps()
if cmap.endswith('_r')])

# Gather all sets together
cmaps = (std_cmaps, std_cmaps_r, all_cmaps, all_cmaps_r)
Expand Down Expand Up @@ -804,106 +806,3 @@ def set_box_value(self, value):

set_box_value(self.type_box, self.type_dict[type(value)])
set_box_value(self.value_box, value)


# Make class with a special box for setting the figsize
class FigSizeBox(BaseBox):
"""
Defines the :class:`~FigSizeBox` class.
This class is used for making the 'figsize' entry in the
:class:`~prism._gui.widgets.preferences.KwargsDictDialogPage` class.
"""

@e13.docstring_substitute(optional=kwargs_doc.format(
'prism._gui.widgets.core.BaseBox'))
def __init__(self, *args, **kwargs):
"""
Initialize an instance of the :class:`~FigSizeBox` class.
%(optional)s
"""

# Call super constructor
super().__init__(*args, **kwargs)

# Create the figsize box
self.init()

# This function creates the figsize box
def init(self):
"""
Sets up the figure size entry after it has been initialized.
This function is mainly responsible for simply creating the two double
spinboxes that allow for the width and height to be set.
"""

# Create the box_layout
box_layout = QW.QHBoxLayout(self)
box_layout.setContentsMargins(0, 0, 0, 0)
self.setToolTip("Figure size dimensions to use for the projection "
"figure")

# Create two double spinboxes for the width and height
# WIDTH
width_box = QW_QDoubleSpinBox()
width_box.setRange(1, 9999999)
width_box.setSuffix("'")
width_box.setStepType(width_box.AdaptiveDecimalStepType)
width_box.setToolTip("Width (in inches) of projection figure")
self.width_box = width_box

# HEIGHT
height_box = QW_QDoubleSpinBox()
height_box.setRange(1, 9999999)
height_box.setSuffix("'")
height_box.setToolTip("Height (in inches) of projection figure")
self.height_box = height_box

# Also create a textlabel with 'X'
x_label = QW.QLabel('X')
x_label.setSizePolicy(QW.QSizePolicy.Fixed, QW.QSizePolicy.Fixed)

# Add everything to the box_layout
box_layout.addWidget(width_box)
box_layout.addWidget(x_label)
box_layout.addWidget(height_box)

# Set default value
set_box_value(self, rcParams['figure.figsize'])

# This function retrieves a value of this special box
def get_box_value(self):
"""
Returns the current width and height of this figsize box and returns
it.
Returns
-------
figsize : tuple
A tuple containing the width and height values of the figsize,
formatted as `(width, height)`.
"""

return((get_box_value(self.width_box), get_box_value(self.height_box)))

# This function sets the value of this special box
def set_box_value(self, value):
"""
Sets the current value of the figsize box to `value`.
Parameters
----------
value : tuple
A tuple containing the width and height values of the figsize,
formatted as `(width, height)`.
"""

set_box_value(self.width_box, value[0])
set_box_value(self.height_box, value[1])
80 changes: 70 additions & 10 deletions prism/_gui/widgets/preferences/kwargs_dicts.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
BaseBox, QW_QComboBox, QW_QDoubleSpinBox, QW_QEditableComboBox, QW_QLabel,
QW_QSpinBox, get_box_value, set_box_value)
from prism._gui.widgets.preferences.custom_boxes import (
ColorBox, ColorMapBox, DefaultBox, FigSizeBox)
ColorBox, ColorMapBox, DefaultBox)

# All declaration
__all__ = ['KwargsDictBoxLayout', 'KwargsDictDialog', 'KwargsDictDialogPage']
Expand Down Expand Up @@ -496,12 +496,13 @@ def add_editable_entry(self):
delete_but.setText('X')

# Determine the number of entries currently in kwargs_grid
n_rows = self.kwargs_grid.count()//3
next_row = self.kwargs_grid.getItemPosition(
self.kwargs_grid.count()-1)[0]+1

# Make a new editable entry
self.kwargs_grid.addWidget(delete_but, n_rows, 0)
self.kwargs_grid.addWidget(kwargs_box, n_rows, 1)
self.kwargs_grid.addWidget(QW.QLabel(''), n_rows, 2)
self.kwargs_grid.addWidget(delete_but, next_row, 0)
self.kwargs_grid.addWidget(kwargs_box, next_row, 1)
self.kwargs_grid.addWidget(QW.QLabel(''), next_row, 2)

# This function deletes an editable entry
@QC.Slot(QW.QComboBox)
Expand Down Expand Up @@ -614,11 +615,6 @@ def create_type_dpi(self):
"figure")
return(dpi_box)

# This function creates a figsize box
@e13.docstring_append(create_type_doc.format('figsize'))
def create_type_figsize(self):
return(FigSizeBox())

# This function creates a linestyle box
@e13.docstring_append(create_type_doc.format('linestyle'))
def create_type_linestyle(self):
Expand Down Expand Up @@ -678,6 +674,70 @@ def create_type_markersize(self):
set_box_value(markersize_box, rcParams['lines.markersize'])
return(markersize_box)

# This function creates a fh_arrowlength box
@e13.docstring_append(create_type_doc.format('fh_arrowlength'))
def create_type_fh_arrowlength(self):
# Make a double spinbox for arrow head length
head_length_box = QW_QDoubleSpinBox()
head_length_box.setRange(0, 9999999)
head_length_box.setDecimals(4)
head_length_box.setToolTip("Scaling factor for the length of the "
"plotted arrow head")
return(head_length_box)

# This function creates a ft_arrowlength box
@e13.docstring_append(create_type_doc.format('ft_arrowlength'))
def create_type_ft_arrowlength(self):
# Make a double spinbox for arrow tail length
tail_length_box = QW_QDoubleSpinBox()
tail_length_box.setRange(0, 9999999)
tail_length_box.setDecimals(2)
tail_length_box.setToolTip("Length of the plotted arrow tail relative "
"to the length of its head")
return(tail_length_box)

# This function creates a fh_arrowwidth box
@e13.docstring_append(create_type_doc.format('fh_arrowwidth'))
def create_type_fh_arrowwidth(self):
# Make a double spinbox for arrow head width
head_length_box = QW_QDoubleSpinBox()
head_length_box.setRange(0, 9999999)
head_length_box.setDecimals(4)
head_length_box.setToolTip("Scaling factor for the width of the "
"plotted arrow head")
return(head_length_box)

# This function creates a ft_arrowwidth box
@e13.docstring_append(create_type_doc.format('ft_arrowwidth'))
def create_type_ft_arrowwidth(self):
# Make a double spinbox for arrow tail width
tail_length_box = QW_QDoubleSpinBox()
tail_length_box.setRange(0, 9999999)
tail_length_box.setDecimals(4)
tail_length_box.setToolTip("Scaling factor for the width of the "
"plotted arrow tail")
return(tail_length_box)

# This function creates a rel_xpos box
@e13.docstring_append(create_type_doc.format('rel_xpos'))
def create_type_rel_xpos(self):
# Make a double spinbox for arrow relative x-position
x_pos_box = QW_QDoubleSpinBox()
x_pos_box.setRange(0, 1)
x_pos_box.setDecimals(4)
x_pos_box.setToolTip("Relative x-position of the arrow.")
return(x_pos_box)

# This function creates a rel_xpos box
@e13.docstring_append(create_type_doc.format('rel_ypos'))
def create_type_rel_ypos(self):
# Make a double spinbox for arrow relative y-position
y_pos_box = QW_QDoubleSpinBox()
y_pos_box.setRange(0, 1)
y_pos_box.setDecimals(4)
y_pos_box.setToolTip("Relative y-position of the arrow.")
return(y_pos_box)

# This function creates a scale box
def create_type_scale(self, axis):
"""
Expand Down

0 comments on commit e6c0a50

Please sign in to comment.