Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Verbosity a Singleton class #1349

Merged
merged 7 commits into from
Sep 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 123 additions & 3 deletions doc/docs/Python_User_Interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -5924,7 +5924,7 @@ Construct an `EigenModeSource`.

+ **`eig_band` [`integer` or `DiffractedPlanewave`]** — Either the index *n* (1,2,3,...) of the desired band
ω<sub>*n*</sub>(**k**) to compute in MPB where 1 denotes the lowest-frequency
band at a given **k** point, and so on, or alternatively a diffracted planewaeve in homogeneous media.
band at a given **k** point, and so on, or alternatively a diffracted planewave in homogeneous media.

+ **`direction` [`mp.X`, `mp.Y`, or `mp.Z;` default `mp.AUTOMATIC`],
`eig_match_freq` [`boolean;` default `True`], `eig_kpoint` [`Vector3`]** — By
Expand Down Expand Up @@ -7001,6 +7001,126 @@ search for. Defaults to 100.

</div>

---
<a id="Verbosity"></a>

### Verbosity

```python
class Verbosity(object):
```

<div class="class_docstring" markdown="1">

A class to help make accessing and setting the global verbosity level a bit
more pythonic. It manages one or more verbosity flags that are located in
the C/C++ libraries used by Meep.

The verbosity levels are:

* 0: minimal output
* 1: a little
* 2: a lot
* 3: debugging

An instace of `Verbosity` is created when meep is imported, and is accessible
as `meep.verbosity`.

Note that this class is a Singleton, meaning that each call to
`Verbosity(cvar)` gives you the same instance. The new `cvar` will be added to a
list of verbosity flags managed by this class.

</div>



<a id="Verbosity.__init__"></a>

<div class="class_members" markdown="1">

```python
def __init__(self, cvar=None, initial_level=None):
```

<div class="method_docstring" markdown="1">

See `add_verbosity_var()`

</div>

</div>

<a id="Verbosity.__call__"></a>

<div class="class_members" markdown="1">

```python
def __call__(self, level):
```

<div class="method_docstring" markdown="1">

Convenience for setting the verbosity level. This lets you set the level
by calling the instance like a function. For example, if `verbosity` is
an instance of this class, then it's value can be changed like this:

```
verbosity(0)
```

</div>

</div>

<a id="Verbosity.add_verbosity_var"></a>

<div class="class_members" markdown="1">

```python
def add_verbosity_var(self, cvar=None, initial_level=None):
```

<div class="method_docstring" markdown="1">

Add a new verbosity flag to be managed. `cvar` should be some object
that has a `verbosity` attribute, such as `meep.cvar` or `mpb.cvar`.

</div>

</div>

<a id="Verbosity.get"></a>

<div class="class_members" markdown="1">

```python
def get(self):
```

<div class="method_docstring" markdown="1">

Returns the current verbosity level.

</div>

</div>

<a id="Verbosity.set"></a>

<div class="class_members" markdown="1">

```python
def set(self, level):
```

<div class="method_docstring" markdown="1">

Validates the range, and sets the global verbosity level. Returns the
former value.

</div>

</div>


Miscellaneous Functions Reference
Expand All @@ -7020,9 +7140,9 @@ This output can be suppressed by calling this function with `True` (the default)
output can be enabled again by passing `False`. This sets a global variable, so the
value will persist across runs within the same script.

</div>
This function is deprecated, please use the [Verbosity](#verbosity) class instead.

@@ verbosity @@
</div>


<a id="interpolate"></a>
Expand Down
8 changes: 6 additions & 2 deletions doc/docs/Python_User_Interface.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -813,15 +813,19 @@ The following classes are available directly via the `meep` package.

@@ Harminv[methods-with-docstrings] @@

@@ Verbosity @@
@@ Verbosity.__init__ @@
@@ Verbosity.__call__ @@
@@ Verbosity.add_verbosity_var @@
@@ Verbosity.get @@
@@ Verbosity.set @@


Miscellaneous Functions Reference
---------------------------------

@@ quiet @@

@@ verbosity @@

@@ interpolate @@

#### Flux functions
Expand Down
3 changes: 3 additions & 0 deletions python/meep.i
Original file line number Diff line number Diff line change
Expand Up @@ -1728,6 +1728,9 @@ PyObject *_get_array_slice_dimensions(meep::fields *f, const meep::volume &where
plot_fields,
Animate2D
)
from .verbosity_mgr import (
Verbosity
)

if with_mpi():
try:
Expand Down
2 changes: 2 additions & 0 deletions python/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -5050,6 +5050,8 @@ def quiet(quietval=True):
This output can be suppressed by calling this function with `True` (the default). The
output can be enabled again by passing `False`. This sets a global variable, so the
value will persist across runs within the same script.

This function is deprecated, please use the [Verbosity](#verbosity) class instead.
"""
verbosity(int(not quietval))

Expand Down
90 changes: 72 additions & 18 deletions python/verbosity_mgr.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,75 @@
class Verbosity(object):
"""
A class to help make accessing and setting the global verbosity level a bit
more pythonic.
more pythonic. It manages one or more verbosity flags that are located in
the C/C++ libraries used by Meep.

Verbosity levels are:
0: minimal output
1: a little
2: a lot (default)
3: debugging
The verbosity levels are:

* 0: minimal output
* 1: a little
* 2: a lot
* 3: debugging

An instace of `Verbosity` is created when meep is imported, and is accessible
as `meep.verbosity`.

Note that this class is a Singleton, meaning that each call to
`Verbosity(cvar)` gives you the same instance. The new `cvar` will be added to a
list of verbosity flags managed by this class.
"""
_instance = None

def __new__(cls, *args, **kw):
# Create the real instance only the first time, and return the same each
# time Verbosity is called thereafter.
if cls._instance is None:
cls._instance = super(Verbosity, cls).__new__(cls)
cls._instance._init()
return cls._instance

def _init(self):
"""
Set up the initial state of the singleton. Called only when the first
instance is created.
"""
self._master_verbosity = 1
self._cvars = list()

def __init__(self, cvar=None, initial_level=None):
"""See `add_verbosity_var()`"""
self.add_verbosity_var(cvar, initial_level)

def add_verbosity_var(self, cvar=None, initial_level=None):
"""
Initialize the Verbosity manager. `cvar` should be some object that has
a `verbosity` attribute, such as meep.cvar or mpb.cvar.
Add a new verbosity flag to be managed. `cvar` should be some object
that has a `verbosity` attribute, such as `meep.cvar` or `mpb.cvar`.
"""
super(Verbosity, self).__init__()
self.cvar = cvar
if cvar is None or not hasattr(cvar, 'verbosity'):
# If we're not given a module.cvar (e.g., while testing) or if the
# cvar does not have a verbosity member (the lib hasn't been updated
# yet) then use a dummy object so things can still run without it.
# cvar does not have a verbosity member (e.g. the lib hasn't been
# updated to have a verbosity flag yet) then use a dummy object so
# things can still run without it.
class _dummy():
verbosity = 1
self.cvar = _dummy()
def __init__(self): self.verbosity = 1
cvar = _dummy()
self._cvars.append(cvar)
if initial_level is not None:
self.set(initial_level)

def get(self):
"""
Returns the current verbosity level.
"""
return self.cvar.verbosity
return self._master_verbosity

def get_all(self):
"""
Return a list of the values of all verbosity flags being managed. This
is mostly intended for debugging this class and won't likely be useful
otherwise.
"""
return [cvar.verbosity for cvar in self._cvars ]

def set(self, level):
"""
Expand All @@ -43,8 +82,10 @@ def set(self, level):
"""
if level < 0 or level > 3:
raise ValueError('Only verbosity levels 0-3 are supported')
old = self.cvar.verbosity
self.cvar.verbosity = level
old = self._master_verbosity
for cvar in self._cvars:
cvar.verbosity = level
self._master_verbosity = level
return old

def __call__(self, level):
Expand Down Expand Up @@ -82,7 +123,17 @@ def __ge__(self, o): return self.get() >= o

def main():
# simple test code
import sys

class MyCvar:
def __init__(self): self.verbosity = 1

verbosity = Verbosity()
v2 = Verbosity(MyCvar())
print(verbosity is v2)
print(id(verbosity), id(v2))
print(verbosity.get_all())

print('initial value: {}'.format(verbosity.get()))

print('v==1: {}'.format(verbosity == 1))
Expand All @@ -93,9 +144,12 @@ def main():
print('v>=2: {}'.format(verbosity >= 2))
print('v<=1: {}'.format(verbosity <= 1))

verbosity(1)
verbosity(3)
print('v==1: {}'.format(verbosity == 1))
print('v==2: {}'.format(verbosity == 2))
print('v==3: {}'.format(verbosity == 3))

print(verbosity.get_all())

# should raise ValueError
verbosity(5)
Expand Down