Skip to main content

Stellar surface maker

Project description

# stasma
STellAr Surface MAker

**Stasma** is python package created to make binary and single star systems modeling easier.
Inside the package, Roche potential is implemented as a generalized implicit description of binary star surface and
simple potential for single rotating star.

Stasma is a precursor for **elisa** package that is currently in development, and it is intended
to be application with full implementation of eclipsing binary star and single star physics including light curve
modeling including pulsations.

## Requirements

Stasma is a python package which requires ``python v3.6+`` and has following dependencies::

cycler==0.10.0
matplotlib==2.1.0
numpy==1.13.3
pandas==0.23.0
pyparsing==2.2.0
pytest==3.2.3
python-dateutil==2.6.1
pytz==2017.2
py==1.4.34
astropy==2.0.2
scipy==1.0.0
six==1.11.0

Nevertheless, versions are specified precisely, it doesn't mean that stasma won't work with higher versions,
it just was not tested with other versions of mentioned python packages.

``stasma`` is multiplatform library fully supported on Linux and Windows operating systems.

## How to

The following guide describes all capabilities and features of this package.

### Install

As an any python package, ``stasma`` the easiest and safer way to install is to create python virtual
environment and install all requirements into it. Here is a simple guide, how to od it. Details of installation differ
in dependence on the selected operating system.

#### Ubuntu [or similar]

First, you have to install Python 3.6 or higher. In newest stable version ``Ubuntu 18.04`` there is already preinstalled
python `3.6.x`. In older verions, you will have to add repository and install it manually.

Install ``pip3`` python package manager if is not already installed on your system, usually by execution of command

apt install -y python3-pip

Install virtual environment by command

pip3 install virtualenv

To create virtual enviroment, create directory where python virual environment will be stored, e.g. ``/<any>/<path>/env36``
and run following command::

virtualenv /<any>/<path>/env36 --python=python3.6

After few moments you virtual enviromnet is created and ready for use. In terminal window, activate virtual environment

. /<any>/<path>/env36/bin/activate

When virtual enviroment is activated, install ``stasma`` by

pip3 install stasma


#### Windows

To install python in windows, download ``python 3.6.x`` installation package from official python web site.
Installation package will create all necessary dependencies with exception of virtual environment.
Install virtual enviroment by exection of following command in command line

pip3 install virtualenv

Make sure a proper version of python and pip is used. When done, create directory where virtual enviroment will be
stored and run

virtualenv /<any>/<path>/env36 --python=python3.6

Now, when virtual enviroment is prepared, run

. /<any>/<path>/env36/Scripts/activate

And finally install ``stasma``

pip3 install stasma

## Configuration

Currently, you have a possibility to configure logging level and logging structure.
By default, logging level is specified by json logging definition deployed in site-packages
(installation directory of all python packages). If you want to enable logging,
just import configuration module and run setup logging function.


from stasma.conf import config

def main():
config.set_up_logging()
...

if __name__ == "__main__":
main()

If you wish to change a logging, define your own json configuration and setup path in stasma configuraion ini file.

[general]
log_config=/<path>/<to>/<logging>/<json>

Configuration ini file has to be supplied eather as environment variable ``STASMA_CONFIG`` or stored in your
virtual environment directory as ``conf/stasma_conf.ini``.

## Important api docs

### ``stasma.base.star.Star:``

class define Star instance

:param name: char; name of instance
:param suppress_logger: bool; enable/disable logger
:param kwargs:
:**kwargs options**:
* **mass** * -- float or astropy.units.Quantity;
mass of Start object

* **surface_potential** * -- float;
unit-less Roche surface potential of Star

* **synchronicity** * -- float;
synchronicity of Star defined in generalized Roche potential as ratio of rotational angular
velocity to orbital angular velocity

* **discretization_factor** * -- float;
average angular distance of two nearest points on Star surface

* **spots** * -- list of dicts;
list of spots definition (see ``from stasma.base.Spot``)

* **mass** * -- float or astropy.units.Quantity;
mass of Start object

* **polar_log_g** * -- float;
polar gravity acceleration in log10 of cgs units

* **color** * -- list; [<0-255>, <0-255>, <0-255>]
color definition for plotting


*important accessible properties computed on fly:*

- critical_surface_potential
- backward_radius
- forward_radius
- polar_radius
- side_radius

<hr><br>

### ``stasma.base.star.Spot:``

**NOTE**:
instances of this class are used as a container for individual spot defined for each Star; it is not indended
to be used stand alone

:param kwargs:
:**kwargs options**:
* **longitude** * -- float;
longitude of spot center

* **latitude** * -- float;
latitude of spot center

* **angular_diameter** * -- float;
angular diameter of spot

* **discretization_factor** * -- float;
discretization factor of spor, if not specified, discretization of parent Star will be used

* **color** * -- list; [<0-255>, <0-255>, <0-255>]
color definition for plotting for given spot

<hr><br>

### ``stasma.single_system.system.SingleSystem``

:param name: char; name of instance
:param suppress_logger: bool; enable/disable loggerd
:param kwargs:
:**kwargs options**:
* **period** * -- stasma.base.star.Star;;
instance of Star
* **inclination** * -- float or astropy.units.Quantity;
inclination of binary system; default unit is `degree`
* **rotation_period** * -- float or astropy.units.Quantity;
rotation period of star; default unit is `day`


##### ``stasma.single_system.system.SingleSystem.build_mesh(self, return_mesh=False)``

user face method for building mesh; as mesh we define a set of points on surface of star objects.

:param return_mesh: bool; if True, return surface points of object (spots included); return value of method will
be numpy.arrays like np.array(<points>)

##### ``stasma.single_system.system.SingleSystem.build_surface(self, return_surface=False)``

user face method to build surface; there is assumption that build_mesh() was called before this method,
otherwise calling this method will lead to crash

:param return_surface: bool; if True, return value of method will be tuple like (points, faces)

##### ``stasma.single_system.system.SingleSystem.plot.equipotential(self, **kwargs)``

:param kwargs:
:**kwargs options**:
* **axis_unit** * -- any astropy.unit lenght unit, eg. astropy.units.solRad, astropy.units.AU,
astropy.units.m, etc. if empty astropy.units.solRad is assumed;

##### ``stasma.single_system.system.SingleSystem.plot.mesh(self, **kwargs)``

:param kwargs:
:**kwargs options**:
* **axis_unit** * -- any astropy.unit lenght unit, eg. astropy.units.solRad, astropy.units.AU,
astropy.units.m, etc. if empty astropy.units.solRad is assumed;
* **plot_axis** * -- enable/disable axis in resulting plot, deafault is True;
* **inclination** * -- angle between rotational axis and line of sight;
* **azimuth** * -- angle between 0 latitude meridian and line of sight;

##### ``stasma.single_system.system.SingleSystem.plot.wireframe(self, **kwargs)``

:param kwargs:
:**kwargs options**:
* **axis_unit** * -- any astropy.unit lenght unit, eg. astropy.units.solRad, astropy.units.AU,
astropy.units.m, etc. if empty astropy.units.solRad is assumed;
* **plot_axis** * -- enable/disable axis in resulting plot, deafault is True;
* **inclination** * -- angle between rotational axis and line of sight;
* **azimuth** * -- angle between 0 latitude meridian and line of sight;

##### ``stasma.single_system.system.SingleSystem.plot.surface(self, **kwargs)``

:param kwargs:
:**kwargs options**:
* **axis_unit** * -- any astropy.unit lenght unit, eg. astropy.units.solRad, astropy.units.AU,
astropy.units.m, etc. if empty astropy.units.solRad is assumed;
* **edges** * -- enable/disable edge highlight of faces, default is True;
* **normals** * -- enable/disable normal vector of faces, default is False;
* **inclination** * -- angle between rotational axis and line of sight;
* **azimuth** * -- angle between 0 latitude meridian and line of sight;
* **units** * -- any astropy.unit lenght unit, eg. astropy.units.solRad, astropy.units.AU,
astropy.units.m, etc. if empty astropy.units.solRad is assumed;
<hr><br>

### ``stasma.binary_system.system.BinarySystem``

:param name: char; name of instance
:param primary: stasma.base.star.Star; instance of primary Star
:param secondary: stasma.base.star.Star; instance of secondary Star
:param suppress_logger: bool; enable/disable logger
:param kwargs:
:**kwargs options**:
* **period** * -- float or astropy.units.Quantity;
period of binary system, default unit is `day`

* **eccentricity** * -- float;
eccentricity of binary system

* **inclination** * -- float or astropy.units.Quantity;
inclination of binary system; default unit is `radian`

* **argument_of_periastron** * -- float or astropy.units.Quantity;
argument_of_periastron of binary system; default unit is `radian`

*user face methods:*

##### ``stasma.binary_system.system.BinarySystem.build_mesh(self, component=None, components_distance=None, return_mesh=False)``

user face method for building mesh; as mesh we define a points surface of star objects.

:param component: str or list; define component to build surface for; if None, surface for both components will be evaluated
:param components_distance: float;
:param return_surface: bool; if True, return points of objects (spots included); return value of method will be dictionary of numpy.arrays like {"primary": np.array(<points>), "secondary": np.array(<points>)}


##### ``stasma.binary_system.system.BinarySystem.build_surface(self, component=None, components_distance=None, return_surface=False)``

user face method to build surface.;There is assumption that build_mesh() was called before this method,
otherwise calling this method will lead to crash

:param component: str or list; define component to build surface for; if None, surface for both components will be evaluated
:param components_distance: float;
:param return_surface: bool; if True, return value of method will be tuple like (points, faces)

##### ``stasma.binary_system.system.BinarySystem.plot.orbit(self, **kwargs)``

:param kwargs:
:**kwargs options**:
* **start_phase** * -- float;
* **stop_phase** * -- float;
* **number_of_points** * -- int;
* **axis_unit** * -- any astropy.unit lenght unit or `dimensionless`, eg. astropy.units.solRad,
astropy.units.AU, astropy.units.m, etc., if empty `dimensionless` is assumed where semi major axis is set to
1;
* **frame_of_reference** * -- str; `primary` or `barycenter`

##### ``stasma.binary_system.system.BinarySystem.plot.equipotential(self, **kwargs)``

:param kwargs:
:**kwargs options**:
* **plane** * -- str; `xy`, `yz`, `zy`
* **phase** * -- float;

##### ``stasma.binary_system.system.BinarySystem.plot.mesh(self, **kwargs)``

:param kwargs:
:**kwargs options**:
* **phase** * -- float;
* **components_to_plot** * -- str; `primary`, `secondary` or `both`
* **plot_axis** * -- bool;
* **inclination** * -- angle between orbital axis and line of sight;
* **azimuth** * -- photometric phase of the system;

##### ``stasma.binary_system.system.BinarySystem.plot.wireframe(self, **kwargs)``

:param kwargs:
:**kwargs options**:
* **phase** * -- float;
* **components_to_plot** * -- str; `primary`, `secondary` or `both`
* **plot_axis** * -- bool;
* **inclination** * -- angle between orbital axis and line of sight;
* **azimuth** * -- photometric phase of the system;

##### ``stasma.binary_system.system.BinarySystem.plot.surface(self, **kwargs)``

:param kwargs:
:**kwargs options**:
* **phase** * -- float;
* **components_to_plot** * -- str; `primary`, `secondary` or `both`
* **normals** * -- bool;
* **edges** * -- bool;
* **plot_axis** * -- bool;
* **inclination** * -- float or wtf;
* **azimuth** * -- float;
* **units** * -- any astropy.unit lenght unit or `dimensionless`, eg. astropy.units.solRad,
astropy.units.AU, astropy.units.m, etc., if empty `dimensionless` is assumed where semi major axis is set to
1;

*important accessible properties computed on fly:*

- semi_major_axis
- morphology
- mass_ratio
- orbit

<hr><br>

### ``stasma.binary_system.orbit.Orbit``

:param suppress_logger: bool; enable/disable logger
:param kwargs:
:**kwargs options**:
* **period** * -- float or astropy.units.Quantity;
period of binary system, default unit is `day`

* **eccentricity** * -- float;
eccentricity of binary system

* **inclination** * -- float or astropy.units.Quantity;
inclination of binary system; default unit is `degree`

* **argument_of_periastron** * -- float or astropy.units.Quantity;
argument_of_periastron of binary system; default unit is `radian`

*user face methods:*

##### ``stasma.binary_system.orbit.Orbit.orbital_motion(self, phase=None)``

function takes photometric phase of the binary system as input and calculates positions of the secondary
component in the frame of reference of primary component

:param phase: np.array or np.float
:return: np.array: matrix consisting of column stacked vectors distance, azimut angle, true anomaly and phase
np.array((r1, az1, ni1, phs1),
(r2, az2, ni2, phs2),
...
(rN, azN, niN, phsN))

*important accessible properties computed on fly:*

- periastron_distance
- periastron_phase

<hr><br>

## Basic examples and usage

#### Create binary sytem

from astropy import units
from stasma.base.star import Star
from stasma.binary_system.system import BinarySystem


def main():

primary = Star(
mass=2.0 * units.solMass,
surface_potential=2.6,
synchronicity=1.0,
discretization_factor=5,
color=[0, 255, 0]
)
secondary = Star(
mass=1.0 * units.solMass,
surface_potential=2.6,
synchronicity=1.0,
discretization_factor=5,
color=[255, 0, 0]
)

bs = BinarySystem(
primary=primary,
secondary=secondary,
argument_of_periastron=90 * units.deg,
period=1 * units.d,
eccentricity=0.0,
inclination=90 * units.deg
)

if __name__ == "__main__":
main()

#### Create single system

from astropy import units
from stasma.base.star import Star
from stasma.single_system.system import SingleSystem


def main():

star = Star(
mass=1.0 * units.solMass,
discretization_factor=3,
polar_log_g=4.1 * units.dex(units.cm / units.s ** 2),
color=[255, 0, 0]
)

single = SingleSystem(
star=star,
inclination=90 * units.deg,
rotation_period=0.5 * units.d
)

if __name__ == "__main__":
main()

#### Create binary sytem with three spots on primary and one spot on secondary component

from astropy import units
from stasma.base.star import Star
from stasma.binary_system.system import BinarySystem

def main():

spots_metadata = {
"primary":
[
{"longitude": 90,
"latitude": 58,
"angular_diameter": 15},
{"longitude": 85,
"latitude": 80,
"angular_diameter": 30},
{"longitude": 45,
"latitude": 90,
"angular_diameter": 30},
],

"secondary":
[
{"longitude": 90,
"latitude": 0,
"angular_diameter": 40},
]
}

primary = Star(
mass=2.0 * units.solMass,
surface_potential=2.6,
synchronicity=1.0,
discretization_factor=4,
spots=spots_metadata['primary'],
color=[0, 255, 0]
)
secondary = Star(
mass=1.0 * units.solMass,
surface_potential=2.6,
synchronicity=1.0,
discretization_factor=4,
spots=spots_metadata['secondary'],
color=[255, 0, 0]
)

bs = BinarySystem(
primary=primary,
secondary=secondary,
argument_of_periastron=90 * units.deg,
period=1 * units.d,
eccentricity=0.0,
inclination=90 * units.deg,
)

if __name__ == "__main__":
main()

### Build mesh and surface of objects in binary system

**NOTE**: parameter `componetn_distance` is driven parameter to involve capability
to compute and create system in different part of eccentric orbit

<br>

**After computation, properties like ``points`` or ``faces`` are available from Star class instaces.**


def main():
...

bs.build_mesh(components_distance=1.0)
bs.build_surface(components_distance=1.0)

print(primary.points)
print(primary.faces)
print(primary.spots)

print(primary.spots[#index].points)
print(primary.spots[#index].faces)

if __name__ == "__main__":
main()

### Build mesh and surface of objects in single system

**After computation, properties like ``points`` or ``faces`` are available from Star class instace.**

def main():
...

single.build_mesh()
single.build_surface()

print(star.points)
print(star.faces)
print(star.spots)

print(star.spots[#index].points)
print(star.spots[#index].faces)

if __name__ == "__main__":
main()


### Plot binary star system wireframe

def main():
...

bs.build_mesh(components_distance=1.0)
bs.build_surface(components_distance=1.0)

bs.plot.wireframe()

if __name__ == "__main__":
main()





Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

stasma-0.1.0.tar.gz (57.1 kB view hashes)

Uploaded Source

Built Distribution

stasma-0.1.0-py36-none-any.whl (57.0 kB view hashes)

Uploaded Python 3.6

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page