Package: nanoscipy
nanoscipynanoscipy has been made, to ease the data-handling, -processing, and - analysis. Additionally, it also provides a
simple way to perform numerical calculations with units.
This package is being readily updated at the moment, so be sure to keep up, as new and useful additions and fixes are
very likely to be included.Installation and updatingUse the package managerpipto install nanoscipy like below.
Rerun this command to check for and install  updates .pipinstallnanoscipyFor package updates, use:pipinstall--upgradenanoscipyNote that if you're using anaconda, you might have to install the module from the anaconda terminal instead (or use
conda rather than pip)ImportClick for detailsCurrently, the package consists of four distinct modules:
```bash
nanoscipy.functions
```
Contains most of the practical functions of nanoscipy.nanoscipy.modulesContains all classes of nanoscipy.nanoscipy.utilContains all utility functions and lists used within nanoscipy. Different modules use functions from this module.
Note that some of these functions may be of practical use, but many are simply throw-away functions to increase
readability.nanoscipy.mathparThe module with the mathematical parser of nanoscipy. Specifically, this contains the practical function parser(), which
is the collective parser itself.nanoscipy.unitparContains a script that allows for computation with units.Getting started with unit computationsClick for detailsThere are two main functions of concern here; `mathpar.parser()` and `unitpar.unit_parser()`, but the focus will be on 
the module `modules.NumAn` as this is what is meant to be the 'calculator'. This section will serve as an explanation of how 
it works and how it may be used for different purposes.
(Last updated: v3.0.8)1) The NumAn objectWhen defining the NumAn object there are a few things to note. The__init__()function takes five different inputs,
all of which are optional. The first isconswhich is where initial constants can be defined so that they may be used
in computations later on (by default no constants are defined), e.g.:importnanoscipy.modulesasnsmcal1=nsm.NumAn('A=234 kg, lambda=53 nm')Will have the constantsAandlambdadefined with the values234 kgand53 nmassigned to them, respectively.
Constants may also be defined via the attribute function.add_cns(), which works in much the same way, so that forimportnanoscipy.modulesasnsmcal2=nsm.NumAn()cal2.add_cns('A=234 kg, lambda=53 nm')the same constants are defined as for thecal1object.
The add-constant attribute does, however, work slightly different, allowing for new constants to be defined with
previously defined constants, socal2.add_cns('A2=4*A')would make it so thatA2=936 kg.
Constants may effectively have any desired name with a few exceptions: The constant must be a string, meaning that it
cannot be converted to a float or int, soB2=34is allowed, but22=34is not. Be aware that constant-values are
substituted before calculations are done, which means that if a constant2H=4is defined, and a calculation is done
for a string'32H'the result is'3*2H=3*4=12'.The second parameter isunit_identifier. This defines an identifier for which units can be told apart from defined
constants by the different scripts. This can in principle be set to any symbol, but be smart about it. The default
value used for this purpose is' ', which is illustrated in the examples above. Another example is seen below forunit_identifier='~'importnanoscipy.modulesasnsmcal3=nsm.NumAn(unit_identifier='~')cal3.add_cns('A=234~kg, lambda=53~nm')cal3.add_cns('A2=4*A')The third parameter isunits. This tells the script whether units should be used or not (explicitly). Effectively,
this only affects natural constants used (seeMore about constants).
Therefore, the default setting isunits=Truemeaning that the script will act as computations should be done with units.
Setting this toFalsewill have the script do calculations without units (effectively). It must although be emphasized that thisonlyaffects natural constants
and so everything is still fine if no units are used initially, as long as no natural constants are used, unless it is
by division or multiplication, in which case it is also fine.The next parameter iscprint. This affects how the result from a computation is displayed (the console print), and affects all
computations if not anything else is set specifically per computation (seeCalculations).
There are a few options here, but the main difference is between'num'and'sym'. If set to'num'the result will
be displayed as themathpar.parser()reads the expression, i.e. with only numbers and mathematical symbols. If set to'sym'the
expression will be displayed with symbols/constants rather than numbers. A variance is'symc', which displays the
constants used in the expression, along with the result. Subtypes are'sym_ex'and'symc_ex', which will display
the main expression with explicit multiplication (if any implicit multiplication was used). If set toNoneorFalseno console print is done. Examples can be found inCalculations. The default setting is'symc_ex'.The last parameter issfwhich sets the significant figures for the console print. It is important to note that it
does not change the significant figures of the calculation itself nor the result. Itonlychanges the console print.
This parameter takes integer values, and can be set toNoneif no evaluation is desired. The default value is 4. Note
that this feature works by using thempmath.workdpsfunction.2) More about constantsThere has already been presented examples of how constants may be defined, but there are a few additional features to
note. A list of all the currently defined constants can be seen by calling the attribute function.constants(). Note
that if constants are defined with units, then they aredisplayedwith' 'as the unit identifier, regardless of the
value ofunit_identifierin the__init__()call. When adding constants that have already been defined, the new
constant value will overwrite the old, and a prompt will be printed in the console. E.g.:cal1=nsm.NumAn('A=234 kg, lambda=53 nm')cal1.add_cns('A=34 g')>>> Constant 'A = 234 kg' has been changed to '34 g'.Constants may also be removed with the attribute function.del_cns(). Simply specify which constants should be removed
in the call. E.g. from the example above:cal1.constants()>>> Currently defined constants:
>>> | lambda = 53 nm
>>> | A = 34 gcal1.del_cns('A, lambda')cal1.constants()>>> Currently defined constants:Note here that.del_cns()can also be used with multiple arguments, rather than with a single string, e.g.:cal1.del_cns('A','lambda')cal1.constants()>>> Currently defined constants:Constants may also be defined from latest computed result by calling the attribute function.add_res()with the name
of the constant, e.g..add_res('omega')will add the latest result from computation as the constant'omega'.Other than the constants that can be defined by the user, there are some pre-defined natural constants, which may be
used in all calculations, in which they might be needed. These are constants such as the Boltzmann constant_k, the
Planck constant_hor the speed of light in a vacuum_c. Note that all constants are denoted with an underscore.
A full list of the supported units can be seen by calling the attribute.supported_physical_constants.
Depending on whetherunitsis set toTrueorFalse, these natural constants will either have associated units or will
simply be the natural constant value with SI units:test=nsm.NumAn(units=False)print(test.supported_physical_constants)>>> ('_hbar=1.0545718176461565e-34', ..., '_mp=1.67262192369e-27')test=nsm.NumAn(units=True)print(test.supported_physical_constants)>>> ('_hbar=(1.0545718176461565e-34 J Hz^-1)', ..., '_mp=(1.67262192369e-27 kg)')3) CalculationsCalculations are performed via the.calc()attribute function. This effectively utilizesunitpar.unit_parser(),
which utilizesmathpar.parser()to compute the numerical part of the expression. An example of basic usage is seen
below:importnanoscipy.modulesasnsmcal=nsm.NumAn()cal.calc('3*5+2^2')>>> Result: 3·5+2^2 = 19
19There are a few things to note here. As seen, the support for mathematical operators is slightly different compared to
normal python. Specifically, there is support for the operations;+, -, *, /, ^, !(currently, there is no support
for the usual way of denoting a power as**). There is also a 'prettifier' built-in, which automatically changes
constants and specific operations to be more in line with how it would look, when simply writing it out on a piece of
paper. An example of this is with the use of constants;cal.add_cns('omega=34 s^-1, d=4 m')cal.calc('domega')>>> Result: d·ω = 136 m s^-1
>>> | ω = 34 s^-1
>>> | d = 4 m
136This also illustrates a feature regarding implicit multiplication, as this is also read properly by the script (which
is why caution must be made, when defining constants). Note also that the units will be in the displayed result from
the console, but they are not a part of the returned output (to obtain the unit, the attribute.__ans_unit__can be
called).
The result from the calculation can be directly added to the list of constants by calling the attribute function.add_res()in the call with a specified name:cal.add_res('v')cal.constants()>>> Currently defined constants:
>>> | omega = 34 s^-1
>>> | d = 4 m
>>> | v = 136 m s^-1Note that a result may be directly added as a constant, by specifying the parameteradd_resin the.calc()call:cal.calc('domega','v',cprint=None)cal.constants()>>> Currently defined constants:
>>> | omega = 34 s^-1
>>> | d = 4 m
>>> | v = 136 m s^-1This also shows use of thecprint(local) kwarg. As opposed to setting the console print option in the__init__()when defining the function as described inThe NumAn object.
When set in.calc()it only changes the console print for that single calculation, and all others will follow the
default set in__init__():cal.calc('2d/omega',cprint='num')>>> Result: 2·(4 m)/(34 s^-1) = 0.2353 m s
0.23529411764705882cal.calc('2domega')>>> Result: 2·d·ω = 272 m s^-1
>>> | ω = 34 s^-1
>>> | d = 4 m
272As seen in the former calculation, the significant figures in the console print differs from the output. This is due to
described evaluation featuresf(The NumAn object). This
parameter can also be set locally with a kwarg per calculation:cal.add_cns('m=12.3432 g, a=834.2325 m s^-2')cal.calc('ma')>>> Result: m·a = 10.3 N
>>> | m = 12.34 g
>>> | a = 834.2 m
10.297098594cal.calc('ma',sf=6)>>> Result: m·a = 10.2971 N
>>> | m = 12.3432 g
>>> | a = 834.233 m
10.297098594As seen, the parameter also affects the displayed constants. Another example (also illustrating the use of natural
constants):cal.add_cns('T=293.15 K')cal.calc('T_k')>>> Result: T·kᴮ = 4.047e-21 J
>>> | T = 293.1 K
4.0473725435e-21Another thing to note is that there is native support for many mathematical functions such as the trigonometric functions,
the natural logarithm, etc. The full list of supported such functions (including the value of pi), can be found by calling
the attribute.__exclusions__. Some examples of use:cal.calc('sin(deg(45))')>>> Result: sin(deg(45)) = 0.8061
0.8060754911159176cal.add_cns('E=0.3 eV')cal.calc('exp(E/_kT)')>>> Result: exp(-E/(kᴮ·T)) = 6.958e-6 a.u.
>>> | T = 293.1 K
>>> | E = 0.3 eV
6.95757565703751e-06cal.calc('sin(2pi)')>>> Result: sin(2·π) = 0
0Note that the natural logarithm is denoted by'ln()', whereas log10 is denoted as'log()'.4) The unitsA note must be made about the functionality of the units. In general, when computing the units, all given units
are converted into their respective SI components and then reduced. At last, if they correspond to adirectlyderived unit
the resulting unit will be changed into that derived unit. It is, however, currently quite limited, what the script can
recognize as a derived unit. Only the base units e.g.N, K, Jand the inverse base units;N^-1, K^-1, J^-1can be
found. If the unit result cannot be recognized as a derived unit, it is simply given as SI units.There is currently support for the vast majority of the SI unit derivatives, excluding the candela derived units. There
is also special support for some other units such as the atomic mass unit (amu or u), Angstrom (Å), atmosphere (atm), etc.
The full list of supported units, can be seen by calling the attribute.supported_units.There is also an important point to be made in regard to denotation of the units in an expression. The working principle
of the units is that they are essentially multiplicative factors, and so all units act like they are just that. With one
very significant exception. When writing units in fractions, if the unit in the denominator consists of multiple units,
only the first of those will be read as being in the denominator. This is best illustrated with an example:importnanoscipy.modulesasnsmtest=nsm.NumAn()test.calc('23 m/2 s')>>> Result: 23 m/2 s = 11.5 m s^-1
11.5test.calc('23 m/2 s g')>>> Result: 23 m/2 s g = 0.0115 m kg s^-1
0.0115As seen in the latter, the expression'23 m/2 s g'is being read as'(23* m/2* s)* g'rather than'23* m/(2* s* g)'.
Due to this, it isalwaysrecommended to write expressions with units in parentheses (this is automatically handled,
when defining constants and using them in expressions, as shown above, so that a constant defined as'A=4 kg'will be
used by the script as'A=(4 kg)), especially as this odd functionality may change in the future, but as of now, the way
to go is:test.calc('23 m/(2 s g)')>>> Result: 23 m/(2 s g) = 1.15e+4 m s^-1 kg^-1
11500Note that there is currently no support for doing square-roots as'sqrt(4 m^2)':test.calc('sqrt(4 m^2)')>>> Result: sqrt(4 m^2) = 2 m^2
2test.calc('(4 m^2)^(1/2)')>>> Result: (4 m^2)^(1/2) = 2 m
25) Tips and tricksIt may be convenient to reduce the amount of code needed to do computations, especially if the script is run in a console
environment rather than an IDE. This can be done by defining the attribute functions as short variables as follows:importnanoscipy.modulesasnsmcal=nsm.NumAn()a=cal.add_cnsd=cal.del_cnsc=cal.calcThen, when adding new constants simply runa(), when deleting constants,d()and when doing computationsc(). E.g.:a('theta=rad(74), gamma=3.412')c('gammacos(theta)')d('gamma')cal.constants()>>> Result: γ·cos(θ) = 0.9405
>>> | θ = 1.292
>>> | γ = 3.412
>>> Currently defined constants:
>>> | theta = 1.29154364647580346) DisclaimerNote importantly that this guide may not be completely up-to-date with the newest version of nanoscipy, as it takes a lot
of time to re-write and keep an overview of what is in and what is missing. Therefore, I will always recommend to check
out thepatch notes.
It is noted in the beginning of the guide, which version the guide is currently up-to-date with.