Giter Site home page Giter Site logo

vrtulka23 / scinumtools Goto Github PK

View Code? Open in Web Editor NEW
5.0 1.0 0.0 1.28 MB

Essential tools for numerical scientific calculations, simulations and data analysis. Besides several useful tools, this package is featuring expression solver, physical units, material properties and dimensional input parameter modules.

Home Page: https://vrtulka23.github.io/scinumtools/

License: MIT License

Python 99.26% Shell 0.08% Emacs Lisp 0.49% HTML 0.17%
convertor expression numerics physics python quantities scientific-computing solver units dimensions

scinumtools's Introduction

PyPI Supported Python Versions PyTest

scinumtools

scinumtools

Python package scinumtools contains essential tools for scientific and numerical calculations, simulation setup and data analysis.

Documentation

For more information, see the scinumtools documentation. The documentation is currently in a process of writing, so any comments and suggestions for improvement are heartily welcomed.

Quick start

The newest release of scinumtools is available on PyPi and can be easily installed using pip package manager:

pip3 install scinumtools

Besides several useful tools, package scinumtools consist of four main submodules: expression solver, physical units, material properties and DIP.

Expression Solver

Using expression solver one can quickly build a custom parser that can process numerical, logical and textual expressions. This module is an integral part of other submodules. For more description and examples of Expression Solver please refer to the documentation. C++ implementation of this module is available in a separate GitHub repository.

>>> from scinumtools.solver import *
>>> class AtomCustom(AtomBase):
>>>     value: str
>>>     def __init__(self, value:str):
>>>         self.value = str(value)
>>>     def __add__(self, other):
>>>         return AtomCustom(self.value + other.value)
>>>     def __gt__(self, other):
>>>         return AtomCustom(len(self.value) > len(other.value))
>>> operators = {'add':OperatorAdd,'gt':OperatorGt,'par':OperatorPar}
>>> steps = [
>>>     dict(operators=['par'],  otype=Otype.ARGS),
>>>     dict(operators=['add'],  otype=Otype.BINARY),
>>>     dict(operators=['gt'],   otype=Otype.BINARY),
>>> ]
>>> with ExpressionSolver(AtomCustom, operators, steps) as es:
>>>     es.solve("(limit + 100 km/s) > (limit + 50000000000 km/s)")
'False'

Physical Units

This submodule has an aim to make calculations with physical units quick and easy. It includes multiple types of units, constants and implements standard numerical operations with physical quantities. Besides that, it features unit convertor, supports calculations with uncertainties and can be used in combination with third party libraries like NumPy, or Decimal. For more description and examples of Physical Units please refer to the documentation. A C++ implementation of this module puq-cpp is currently in preparation.

>>> import numpy as np
>>> from scinumtools.units import Quantity, Unit
>>> Quantity(23.34, 'kg*m2/s2').to('erg')     # unit conversions
Quantity(2.334e+08 erg)
>>> u = Unit()                                # calculations with units
>>> 34*u.cm + 53*u.dm  
Quantity(5.640e+02 cm)
>>> Quantity(23.34, 'cm', abse=0.03)          # uncertainities
Quantity(2.3340(30)e+01 cm)
>>> Quantity(3, 'A').value('dBA')             # logarithmic units
9.542425094393248
>>> np.sqrt(Quantity([23,59,20,10], 'm2'))    # arrays and NumPy
Quantity([4.796 7.681 4.472 3.162] m)

Material Properties

Simulation setups often require atomic and molecular properties of various materials. The core of this submodule, molecular expression solver, is designed to simplify calculations of such properties from a given molecular formula. For more description and examples of Material Properties please refer to the documentation.

>>> from scinumtools.units import Quantity
>>> from scinumtools.materials import Substance
>>> s = Substance('H2O', natural=False, mass_density=Quantity(997,'kg/m3'), volume=Quantity(1,'l'))
>>> s.print()
Components:

expr element  isotope  ionisation  mass[Da]  count  Z  N  e
   H       H        1           0  1.007825    2.0  1  0  1
   O       O       16           0 15.994915    1.0  8  8  8

Composite:

Total mass:     Quantity(1.801e+01 Da)
Total number:   3.0

expr  mass[Da]         Z        N         e       x[%]       X[%]
   H  2.015650  2.000000 0.000000  2.000000  66.666667  11.191487
   O 15.994915  8.000000 8.000000  8.000000  33.333333  88.808513
 avg  6.003522  3.333333 2.666667  3.333333  33.333333  33.333333
 sum 18.010565 10.000000 8.000000 10.000000 100.000000 100.000000

Matter:

Mass density:   Quantity(9.970e-01 g*cm-3)
Number density: Quantity(3.334e+22 cm-3)
Volume:         Quantity(1.000e+00 l)
Mass:           Quantity(9.970e+02 g)

expr      n[cm-3]  rho[g/cm3]            N       M[g]
   H 6.667280e+22    0.111579 6.667280e+25 111.579129
   O 3.333640e+22    0.885421 3.333640e+25 885.420871
 avg 3.333640e+22    0.332333 3.333640e+25 332.333333
 sum 1.000092e+23    0.997000 1.000092e+26 997.000000

Dimensional Input Parameters

DIP is a serialization language that was designed to collect, manage, convert, document and validate dimensional input parameters used by numerical codes. The main goal of this package is to help developers to focus less on initialization processes mentioned above and more on actual code development. DIP should serve as a quick tool that makes user interface with the code clear and straightforward. For more description and examples of DIP please refer to the documentation.

>>> from scinumtools.dip import DIP, Format
>>> with DIP() as dip:
>>>     dip.add_source("settings", 'settings.dip')
>>>     dip.add_unit("length", 1, "m")
>>>     dip.add_string("""
>>>     box
>>>       width float = 23 [length]
>>>       height float = 11.5 cm
>>>     sphere
>>>       radius float = {settings?sphere.radius}
>>>     """)
>>>     env = dip.parse()
>>>     env.data(Format.TUPLE)
{'box.width': (23.0, '[length]'), 'box.height': (11.5, 'cm'), 'sphere.radius': (34.2, 'mm')}

Alternative Python module dipl implements basic loading and dumping functionality of DIP and provides quick solution for data parsing using DIP.

>>> import dipl
>>>
>>> dipl.load("""
>>> width float = 173.34 cm
>>> age int = 24 yr
>>> """)
{'width': (173.34, 'cm'), 'age': (24, 'yr')}
>>>
>>> dipl.dump({
>>> 'children': ['John','Jenny','Jonah'],
>>> 'car': True
>>> })
children str[3] = ["John","Jenny","Jonah"]
car bool = true

scinumtools's People

Contributors

vrtulka23 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

scinumtools's Issues

Input parameters during caching

Implement a new functionality into CachedFunction that makes a hash from input parameters and stores multiple cached values according to the hash.

Implement system unit arithmetics

Following operations should be implemented:

>>> 23 * AU.Length
Quantity(2.300e+01 #ALEN)
>>> Quantity(23, 's-1') * AU.Length
Quantity(2.300e+01 #ALEN*s-1)

Change documentation code format in DIP

Change the following code format in DIP documentation

with DIP() as dip:
    dip.from_file('definitions.dip')
    env3 = dip.parse()
    data = env.data(format=Format.TYPE)

# data = {
#     'runtime.t_max':        FloatType(1e-08, 's'),
#     'runtime.timestep':     FloatType(1e-11, 's'),
# }

to

>>> with DIP() as dip:
>>>     dip.from_file('definitions.dip')
>>>     env3 = dip.parse()
>>>     env.data(format=Format.TYPE)
{
     'runtime.t_max':        FloatType(1e-08, 's'),
     'runtime.timestep':     FloatType(1e-11, 's'),
}

Improve performance of unit module

Too much time is being spend by calling following functions (cProfile/pstats).
Especially fraction.py and dimensions.py should be rewritten in a way so that they don't need post_init checking, because they are called the most.

  Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     3333    0.038    0.000    0.060    0.000 /home/ubuntu/environment/scinumtools/src/scinumtools/units/fraction.py:13(__post_init__)
    25122    0.019    0.000    0.019    0.000 {built-in method builtins.isinstance}
      404    0.013    0.000    0.054    0.000 /home/ubuntu/environment/scinumtools/src/scinumtools/units/dimensions.py:21(__post_init__)
    14948    0.011    0.000    0.011    0.000 {method 'endswith' of 'str' objects}
      101    0.011    0.000    0.021    0.000 /home/ubuntu/environment/scinumtools/src/scinumtools/units/unit_solver.py:73(<listcomp>)
     3333    0.009    0.000    0.009    0.000 /home/ubuntu/environment/scinumtools/src/scinumtools/units/fraction.py:51(reduce)
    10688    0.008    0.000    0.008    0.000 {built-in method builtins.getattr}
      200    0.008    0.000    0.023    0.000 /home/ubuntu/.local/lib/python3.10/site-packages/numpy/lib/arraysetops.py:524(in1d)
     3333    0.007    0.000    0.067    0.000 <string>:2(__init__)
      200    0.005    0.000    0.009    0.000 /home/ubuntu/.local/lib/python3.10/site-packages/numpy/lib/arraysetops.py:323(_unique1d)
      101    0.004    0.000    0.048    0.000 /home/ubuntu/environment/scinumtools/src/scinumtools/solver/solver.py:48(solve)
      101    0.003    0.000    0.028    0.000 /home/ubuntu/environment/scinumtools/src/scinumtools/units/dimensions.py:48(__add__)
      909    0.003    0.000    0.005    0.000 /home/ubuntu/environment/scinumtools/src/scinumtools/solver/solver.py:77(<listcomp>)
      100    0.003    0.000    0.005    0.000 /home/ubuntu/environment/scinumtools/src/scinumtools/units/unit_types.py:17(convert)
      101    0.003    0.000    0.155    0.002 /home/ubuntu/environment/scinumtools/src/scinumtools/units/base_units.py:50(__init__)
      808    0.003    0.000    0.019    0.000 /home/ubuntu/environment/scinumtools/src/scinumtools/units/fraction.py:70(__add__)
      808    0.002    0.000    0.019    0.000 /home/ubuntu/environment/scinumtools/src/scinumtools/units/fraction.py:80(__mul__)
      101    0.002    0.000    0.033    0.000 /home/ubuntu/environment/scinumtools/src/scinumtools/units/unit_solver.py:54(AtomParser)
      100    0.002    0.000    0.004    0.000 /home/ubuntu/environment/scinumtools/src/scinumtools/units/dimensions.py:78(__eq__)
      101    0.002    0.000    0.026    0.000 /home/ubuntu/environment/scinumtools/src/scinumtools/units/dimensions.py:66(__mul__)

Progress bar with exception

Currently ProgresBar sets 100% progress even if error occured during some step.
Ideally, counting bar stop counting when an error occures.

Fix parsing

dip = DIP()
dip.from_file('settings.dip')
dip.parse()
Traceback (most recent call last):
File "", line 1, in
File "/opt/homebrew/lib/python3.11/site-packages/scinumtools/dip/dip.py", line 130, in parse
node = self._determine_node(line)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/scinumtools/dip/dip.py", line 242, in _determine_node
raise Exception(f"Incorrect format: {code}")
^^^^
NameError: name 'code' is not defined. Did you mean: 'node'?

Numerical quantity check

Implement a quick check if dimensions are zero to substitute

assert unit1.baseunits.dimensions != Dimensions()

with e.g.:

assert unit1.baseunits.dimensionless

Return quantities in DIP

Return parsed numerical DIP values as Quantity objects. A special Format.QUANTITY has to be implemented.

Fix conditions

Following return integralsLevel in the data even though the case is false:

sim
  oneLevelIntegralsOnly bool = false      # Whether to compute intgral quantities only on
                                          # cells at one refinement level, ignoring all finer or coarser cells

  @case ("{?sim.oneLevelIntegralsOnly}")
    # if sim_oneLevelIntegralsOnly is TRUE, this gives the
    # requested refinement level, either explicitly as a positive integer
    # or as -1 for the largest currently realized level.
    integralsLevel int = -1
      !condition ("{?}==-1 || {?}>=1")
  @end

Substraction of scalars from dimensionless quantities

>>> import scinumtools as snt
>>> a = snt.quant(34)
>>> a -= 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "scinumtools/phys/units/QuantityClass.py", line 107, in __sub__
    return self._sub(self, other)
  File "scinumtools/phys/units/QuantityClass.py", line 101, in _sub
    magnitude = left.magnitude - right.to(left.baseunits).magnitude
  File "scinumtools/phys/units/QuantityClass.py", line 298, in to
    unit2 = Quantity(1,units)
  File "scinumtools/phys/units/QuantityClass.py", line 53, in __init__
    self.magnitude *= unit.magnitude
AttributeError: 'NoneType' object has no attribute 'magnitude'

Support for DIP parameter name patterns

Parameters with names like this

rt_mgdXBounds_1 = 1.0e-01
rt_mgdXBounds_2 = 1.0e+00
rt_mgdYBounds_3 = 1.0e+01
rt_mgdYBounds_4 = 1.0e+02
rt_mgdZBounds_5 = 1.0e+03
rt_mgdZBounds_6 = 1.0e+04

could be defined in DIP like e.g.

rt_mgd*Bounds_* float eV
    !pattern ['X','Y','Z'] 
    !pattern "[0-9]{3}"

in order to avoid repeating patters

Implement parameter combination iterator

Simulation settings

SIMULATIONS = {}
for prod in itertools.product(
range(len(nlayers_vacuum)),
range(len(nlayers_fuel)),
range(len(nlayers_gold)),
range(len(vel_gold))
):
nvacuum,nfuel,ngold,vgold = prod

sin() function with Nan baseunits

Using sin() function with dimensionless Quantity gives following error:

Exception: ('Unsupported conversion between units:', None, 'rad')

Add "per-mol" conversion

Something like this should be possible Quantity(40.102833,'Da').to('Da/mol').
Simply multiplying the unit mass by the Avogadro's constant.

ParameterTable dictionary selector

Add possibility to access parameters as object parameters if "keys=True":

>>> pt = ParameterTable(['col1','col2'],{
>>> 'row1': ['a','b']
>>> }, keys=True)
>>> print(pt.row1.col1)
'a'

Improve NormalizeData

Initialize NormalizeData with data columns

with snt.NormalizeData(xaxis=True, yaxis=True, xdata, ydata) as n:

If zdata is a scalar, following error ocures:

    zminpos = np.nanmin(vdata[vdata>0]) if np.sum(vdata>0) else np.nan
TypeError: '>' not supported between instances of 'list' and 'int'

Ideally, one would set x and y first and then the z data values

Reduction of base units

Add automatic and/or triggered reduction of complicated base units.

>>> import scinumtools as snt
>>> q = snt.quant(23, 'km/s')
>>> q *= snt.quant(2, 'h')
>>> q
Quantity(4.600e+01 km*s-1*h)
>>> q.to('km')
Quantity(1.656e+05 km)

In this case, it would be nice if resulting quantity would be already given in "km" instead of "kms-1h"

Icons

Add pretty icons for scinumtools, physical units and solver modules into documentation.

DIP tables with complex data

Make a solution for DIP table blocks with following columns:

id int
desc str
size float cm
points[3] int

1 "Some long text" 23.3 [2,34,4]

Fix summation of Decimal values

Summation of quantities with Decimal magnitudes gives following error:

>>> Quantity(Decimal(2.34234923498499399204), 'cm') + Quantity(Decimal(23993.2340184099288340099), 'm')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ubuntu/.local/lib/python3.10/site-packages/scinumtools/units/quantity.py", line 80, in __add__
    return self._add(self, other)
  File "/home/ubuntu/.local/lib/python3.10/site-packages/scinumtools/units/quantity.py", line 71, in _add
    magnitude = c.add(left, right)
  File "/home/ubuntu/.local/lib/python3.10/site-packages/scinumtools/units/unit_types.py", line 27, in add
    return unit1.magnitude + unit2.to(unit1.baseunits).magnitude
  File "/home/ubuntu/.local/lib/python3.10/site-packages/scinumtools/units/quantity.py", line 221, in to
    self.magnitude = self._convert(self.magnitude, self.baseunits, baseunits)
  File "/home/ubuntu/.local/lib/python3.10/site-packages/scinumtools/units/quantity.py", line 198, in _convert
    return c.convert(magnitude1)
  File "/home/ubuntu/.local/lib/python3.10/site-packages/scinumtools/units/unit_types.py", line 20, in convert
    getattr(self, self.conversion[0])(magnitude1.value * self.baseunits1.magnitude, *self.conversion[1:]) / self.baseunits2.magnitude,
TypeError: unsupported operand type(s) for *: 'decimal.Decimal' and 'float'

ThumbnailImage

  • make the extent parameter optional... default (0,1,0,1)
  • allow to load images from file

Append dict to RowCollector

Modify RowCollector so that it can be set without specifying columns and rows can be inputted as dictionaries.
The columns should be created automatically with the first appending.

Simplify folder structure

  • move all single classes to the main directory off the module
  • keep solver and units in a separate directory

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.