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

New Plasma restructure using networkx #215

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
a2ae0df
adding a new plasma structure
wkerzendorf Feb 3, 2015
d9e2bfb
first attempt to do the networkx plasma
wkerzendorf Feb 3, 2015
d2a5829
first tests with the new plasma system
wkerzendorf Feb 4, 2015
bfe025c
still in the phase of adding networkx to plasma
wkerzendorf Feb 5, 2015
2899390
added getattr stuff
wkerzendorf Feb 5, 2015
61fcbc0
added inpout and getattr
wkerzendorf Feb 5, 2015
d991602
added update skeleton
wkerzendorf Feb 5, 2015
e05877b
added test with atomic data dependency
wkerzendorf Feb 5, 2015
da5f5a0
working tests
wkerzendorf Feb 5, 2015
5d27a49
further improvements to the new plasma class.
wkerzendorf Feb 7, 2015
9a4e0af
generating plasma overview latex graph
wkerzendorf Feb 7, 2015
de6c210
added documentation, doesn't quite work yet
wkerzendorf Feb 7, 2015
88b9a96
begin of restructuring atomic api
wkerzendorf Feb 7, 2015
ff86184
added the atomic data stuff
wkerzendorf Feb 7, 2015
b82a6f5
adding Saha ionization to the new plasma
wkerzendorf Feb 7, 2015
144ee02
transferred most of the plasma functions into the new structure
wkerzendorf Feb 8, 2015
d577114
restructuring the documentation system
wkerzendorf Feb 8, 2015
164d7be
further restructuring to autodetect the inputs from the calculate cal…
wkerzendorf Feb 9, 2015
6c2829b
figuring out ionization calculation
wkerzendorf Feb 9, 2015
903654f
calculating lte up to level populations
wkerzendorf Feb 9, 2015
2cafa82
working simple lte plasma - off to write some tests
wkerzendorf Feb 10, 2015
03a43fb
finished tests for general_properties
wkerzendorf Feb 10, 2015
7b6835f
continue to write the tests
wkerzendorf Feb 11, 2015
a488274
added test_partition_function script
wkerzendorf Feb 11, 2015
3118727
massive change of structure
wkerzendorf Mar 2, 2015
f455950
restructure to properties complete
wkerzendorf Mar 7, 2015
26535b8
fixed the pep8
wkerzendorf Mar 7, 2015
9980beb
fixed most of the documentation
wkerzendorf Mar 7, 2015
03937af
added a stump for BetaSobolev
wkerzendorf Mar 11, 2015
95a067f
removed transition probabilities module for now
wkerzendorf Mar 11, 2015
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
12 changes: 10 additions & 2 deletions tardis/atomic.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,12 +358,20 @@ def from_hdf5(cls, fname=None):
def __init__(self, atom_data, ionization_data, levels_data, lines_data, macro_atom_data=None, zeta_data=None,
collision_data=None, synpp_refs=None, ion_cx_data=None):

if levels_data is not None:
self.has_levels = True
else:
self.has_levels = False

if lines_data is not None:
self.has_lines = True
else:
self.has_lines = False

if macro_atom_data is not None:
self.has_macro_atom = True
self.macro_atom_data_all = DataFrame(macro_atom_data[0].__array__())
self.macro_atom_references_all = DataFrame(macro_atom_data[1].__array__())

else:
self.has_macro_atom = False

Expand Down Expand Up @@ -431,7 +439,7 @@ def __init__(self, atom_data, ionization_data, levels_data, lines_data, macro_at




self.ion_cx_data = ion_cx_data



Expand Down
33 changes: 32 additions & 1 deletion tardis/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,35 @@ def pytest_report_header(config):
if not six.PY3:
s = s.encode(stdoutencoding, 'replace')

return s
return s


import os

@pytest.fixture
def atomic_data_fname():
atomic_data_fname = pytest.config.getvalue("atomic-dataset")
if atomic_data_fname is None:
pytest.skip('--atomic_database was not specified')
else:
return os.path.expandvars(os.path.expanduser(atomic_data_fname))

from tardis.atomic import AtomData

@pytest.fixture
def kurucz_atomic_data(atomic_data_fname):
atomic_data = AtomData.from_hdf5(atomic_data_fname)

if atomic_data.md5 != '21095dd25faa1683f4c90c911a00c3f8':
pytest.skip('Need default Kurucz atomic dataset '
'(md5="21095dd25faa1683f4c90c911a00c3f8"')
else:
return atomic_data

@pytest.fixture
def included_he_atomic_data():
import os, tardis
atomic_db_fname = os.path.join(tardis.__path__[0], 'tests', 'data',
'chianti_he_db.h5')
return AtomData.from_hdf5(atomic_db_fname)

Binary file removed tardis/data/density_sets.h5
Binary file not shown.
12 changes: 0 additions & 12 deletions tardis/data/lucy99_general_default.ini

This file was deleted.

2 changes: 2 additions & 0 deletions tardis/plasma/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from tardis.plasma.base import BasePlasma
from tardis.plasma.standard_plasmas import LTEPlasma
189 changes: 189 additions & 0 deletions tardis/plasma/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import logging

import networkx as nx
from tardis.plasma.exceptions import PlasmaMissingModule, NotInitializedModule

import tempfile


logger = logging.getLogger(__name__)


class BasePlasma(object):

def __init__(self, plasma_modules, **kwargs):
self.module_dict = {}
self.input_modules = []
self._init_modules(plasma_modules, **kwargs)
self._build_graph()
self.update(**kwargs)


def __getattr__(self, item):
if item in self.module_dict:
return self.get_value(item)
else:
super(BasePlasma, self).__getattribute__(item)


def __setattr__(self, key, value):
if key != 'module_dict' and key in self.module_dict:
raise AttributeError('Plasma inputs can only be updated using '
'the \'update\' method')
else:
super(BasePlasma, self).__setattr__(key, value)

def __dir__(self):
attrs = [item for item in self.__dict__
if not item.startswith('_')]
attrs += [item for item in self.__class__.__dict__
if not item.startswith('_')]
attrs += self.module_dict.keys()

return attrs

def get_value(self, item):
return self.module_dict[item].value

def _build_graph(self):
"""
Builds the directed Graph using network X

:param plasma_modules:
:return:
"""

self.graph = nx.DiGraph()

## Adding all nodes
self.graph.add_nodes_from([(key, {})
for key, value in self.module_dict.items()])

#Flagging all input modules
self.input_modules = [key for key, item in self.module_dict.items()
if not hasattr(item, 'inputs')]

for plasma_module in self.module_dict.values():
#Skipping any module that is an input module
if plasma_module.name in self.input_modules:
continue

for input in plasma_module.inputs:
if input not in self.graph:
raise PlasmaMissingModule('Module {0} requires input '
'{1} which has not been added'
' to this plasma'.format(
plasma_module.name, input))
self.graph.add_edge(input, plasma_module.name)

def _init_modules(self, plasma_modules, **kwargs):
"""
Builds a dictionary with the plasma module names as keys
:param plasma_modules:
:return:
"""

self.module_dict = {}
for module in plasma_modules:
if hasattr(module, 'set_value'):
if module.name not in kwargs:
raise NotInitializedModule('Input {0} required for '
'plasma but not given when '
'instantiating the '
'plasma'.format(module.name))
current_module_object = module()
else:
current_module_object = module(self)

self.module_dict[module.name] = current_module_object

def update(self, **kwargs):
for key in kwargs:
if key not in self.module_dict:
raise PlasmaMissingModule('Trying to update property {0}'
' that is unavailable'.format(key))
self.module_dict[key].set_value(kwargs[key])

for module_name in self._resolve_update_list(kwargs.keys()):
self.module_dict[module_name].update()

def _update_module_type_str(self):
for node in self.graph:
self.module_dict[node]._update_type_str()

def _resolve_update_list(self, changed_modules):
"""
Returns a list of all plasma models which are affected by the
changed_modules due to there dependency in the
the plasma_graph.

Parameters
----------

graph: ~networkx.Graph
the plasma graph as
changed_modules: ~list
all modules changed in the plasma

Returns
-------

: ~list
all affected modules.
"""

descendants_ob = []

for module in changed_modules:
descendants_ob += nx.descendants(self.graph, module)

descendants_ob = list(set(descendants_ob))
sort_order = nx.topological_sort(self.graph)

descendants_ob.sort(key=lambda val: sort_order.index(val) )

logger.debug('Updating modules in the following order:'.format(
'->'.join(descendants_ob)))

return descendants_ob

def write_to_dot(self, fname):
self._update_module_type_str()

try:
import pygraphviz
except ImportError:
raise ImportError('pygraphviz is needed for method '
'\'write_to_dot\'')

for node in self.graph:
self.graph.node[node]['label'] = self.module_dict[node].get_latex_label()
self.graph.node[node]['color'] = 'red'
self.graph.node[node]['shape'] = 'box '

nx.write_dot(self.graph, fname)

def write_to_tex(self, fname):
try:
import dot2tex
except ImportError:
raise ImportError('dot2tex is needed for method\'write_to_tex\'')

temp_fname = tempfile.NamedTemporaryFile().name

self.write_to_dot(temp_fname)

dot_string = open(temp_fname).read()

open(fname, 'w').write(dot2tex.dot2tex(dot_string, texmode='raw'))



class StandardPlasma(BasePlasma):

def __init__(self, number_densities, atom_data, time_explosion,
delta_treatment=None, nlte_config=None, ionization_mode='lte',
excitation_mode='lte'):

pass

22 changes: 22 additions & 0 deletions tardis/plasma/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class PlasmaException(Exception):
pass

class IncompleteAtomicData(PlasmaException):
def __init__(self, atomic_data_name):
message = ('The current plasma calculation requires {0}, '
'which is not provided by the given atomic data'.format(
atomic_data_name))
super(PlasmaException, self).__init__(message)


class PlasmaMissingModule(PlasmaException):
pass

class PlasmaIsolatedModule(PlasmaException):
pass

class NotInitializedModule(PlasmaException):
pass

class PlasmaIonizationError(PlasmaException):
pass
8 changes: 8 additions & 0 deletions tardis/plasma/properties/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from tardis.plasma.properties.atomic import *
from tardis.plasma.properties.general import *
from tardis.plasma.properties.ion_population import *
from tardis.plasma.properties.level_population import *
from tardis.plasma.properties.partition_function import *
from tardis.plasma.properties.plasma_input import *
from tardis.plasma.properties.radiative_properties import *

Loading