# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

#
# # Quickstart
#
#
# ## Creating an isotherm
#
# First, we need to import the package.

import pygaps as pg

# The backbone of the framework is the PointIsotherm class. This class stores the isotherm
# data alongside isotherm properties such as the material, adsorbate and temperature, as well
# as providing easy interaction with the framework calculations. 
# There are several ways to create a PointIsotherm object:
#
# - directly from arrays
# - from a pandas.DataFrame
# - parsing json, csv files, or excel files
# - loading from an sqlite database
#
# See the [isotherm creation](../manual/isotherm.rst) part of the 
# documentation for a more in-depth explanation. 
# For the simplest method, the data can be passed in as arrays of *pressure* and *loading*. 
# There are four other required parameters: 
# the material name, the material batch or ID, the adsorbate
# used and the temperature (in K) at which the data was recorded.

isotherm = pg.PointIsotherm(
    pressure=[0.1, 0.2, 0.3, 0.4, 0.5, 0.4, 0.35, 0.25, 0.15, 0.05],
    loading=[0.1, 0.2, 0.3, 0.4, 0.5, 0.45, 0.4, 0.3, 0.15, 0.05],
    material= 'Carbon X1',
    adsorbate = 'N2',
    temperature = 77,
)

# To see a summary of the isotherm, use the `print` function:

print(isotherm)

# Unless specified, the loading is read in *mmol/g* and the
# pressure is read in *bar*. Parameters specified can modify units to anything
# from *weight% vs Pa*,  *mol/cm3 vs relative pressure* to *cm3/mol vs torr*.
# Read more about how pyGAPS handles units in this [section](../manual/units.rst) of the manual.
# The isotherm can also have other properties which are passed in at creation. 
#
# Alternatively, the data can be passed in the form of a pandas.DataFrame.
# This allows for other complementary data, such as isosteric enthalpy, XRD peak intensity, or other
# simultaneous measurements corresponding to each point to be saved.
#
# The DataFrame should have at least two columns: the pressures
# at which each point was recorded, and the loadings for each point.
# The `loading_key` and `pressure_key` parameters specify which column in the DataFrame
# contain the loading and pressure, respectively. The `other_keys` parameter
# should be a list of other columns to be saved.

# +
import pandas as pd

data = pd.DataFrame({
    'pressure': [0.1, 0.2, 0.3, 0.4, 0.5, 0.45, 0.35, 0.25, 0.15, 0.05],
    'loading': [0.1, 0.2, 0.3, 0.4, 0.5, 0.5, 0.4, 0.3, 0.15, 0.05],
    'isosteric_enthalpy [kJ/mol]': [15, 14, 13.5, 13, 12, 11, 10, 10, 10, 10],
    'unimportant_data': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]  # This will not be saved!
})

isotherm = pg.PointIsotherm(
    isotherm_data=data,
    pressure_key='pressure',
    loading_key='loading',
    other_keys=['isosteric_enthalpy [kJ/mol]'],
    
    material= 'Carbon X1',
    adsorbate = 'N2',
    temperature = 77,
    
    pressure_unit='bar',
    pressure_mode='absolute',
    loading_unit='mmol',
    loading_basis='molar',
    material_unit='g',
    material_basis='mass',
    
    material_batch = 'Batch 1',
    iso_type='characterisation'
)
# -

# A summary and a plot can be generated by using the `print_info` function.

isotherm.print_info(y2_range=[0, 20])

# pyGAPS also comes with a variety of parsers. Here we can use the JSON parser to get an isotherm previously saved on disk. For more info on parsing to and from various formats see the [manual](../manual/parsing.rst) and the associated [examples](../examples/parsing.ipynb).

isotherm = pg.isotherm_from_json(r'data/carbon_x1_n2.json')

# To see just a plot of the isotherm, use the `plot` function:

isotherm.plot()

# Isotherms can be plotted in different units/modes, or can be permanently converted. If conversion is desired, find out more in [this section](../manual/isotherm.rst#converting-isotherm-units-modes-and-basis). For example, using the previous isotherm. 

# This just displays the isotherm in a different unit
isotherm.plot(pressure_unit='torr', loading_basis='percent')
print(f"Isotherm is still in {isotherm.pressure_unit} and {isotherm.loading_unit}.")

# While the underlying units can be completely converted
isotherm.convert(pressure_mode='relative')
print(f"Isotherm is now permanently in {isotherm.pressure_mode} pressure.")

# Now that the PointIsotherm is created, we are ready to do some analysis.
#
# ---

# ## Isotherm analysis
#
# The framework has several isotherm analysis tools which are commonly used to characterise
# porous materials such as:
#
# - BET surface area
# - the t-plot method / alpha s method
# - mesoporous PSD (pore size distribution) calculations
# - microporous PSD calculations
# - DFT kernel fitting PSD methods
# - isosteric enthalpy of adsorption calculation
# - etc.
#
# All methods work directly with generated Isotherms. For example, to perform a tplot analysis and get the results in a dictionary use:

# +
result_dict = pg.t_plot(isotherm)

import pprint
pprint.pprint(result_dict)
# -

# If in an interactive environment, such as iPython or Jupyter, it is useful to see the
# details of the calculation directly. To do this, increase the verbosity of the method to display extra information, including graphs:

result_dict = pg.area_BET(isotherm, verbose=True)

# Depending on the method, different parameters can be passed to tweak the way the
# calculations are performed. For example, if a mesoporous size distribution is
# desired using the Dollimore-Heal method on the desorption branch of the isotherm,
# assuming the pores are cylindrical and that adsorbate thickness can
# be described by a Halsey-type thickness curve, the code will look like:

result_dict = pg.psd_mesoporous(
    isotherm,
    psd_model='DH',
    branch='des',
    pore_geometry='cylinder',
    thickness_model='Halsey',
    verbose=True,
)

# For more information on how to use each method, check the [manual](../manual/characterisation.rst) and the associated [examples](../examples/characterisation.rst).
#
# ---

# ## Isotherm modelling
#
# The framework comes with functionality to fit point isotherm data with common
# isotherm models such as Henry, Langmuir, Temkin, Virial etc.
#
# The modelling is done through the ModelIsotherm class. The class is similar to the
# PointIsotherm class, and shares the same ability to store parameters. However, instead of
# data, it stores model coefficients for the model it's describing.
#
# To create a ModelIsotherm, the same parameters dictionary / pandas DataFrame procedure can
# be used. But, assuming we've already created a PointIsotherm object, we can just pass 
# it to the `pygaps.model_iso` function.

model_iso = pg.model_iso(isotherm, model='DSLangmuir', verbose=True)

# A minimisation procedure will then attempt to fit the model's parameters to the isotherm points.
# If successful, the ModelIsotherm is returned.
#
# In the user wants to screen several models at once, the class method can also be passed a
# parameter which allows the ModelIsotherm to select the best fitting model. Below, we 
# will attempt to fit several simple available models, and the one with the best RMSE will be
# returned. Depending on the models requested, this method may take significant processing time.

model_iso = pg.model_iso(isotherm, model='guess', verbose=True)

# More advanced settings can also be specified, such as the optimisation model to be used in the
# optimisation routine or the initial parameter guess. For in-depth examples and discussion check the [manual](../manual/modelling.rst) and the associated [examples](../examples/modelling.rst).
#
# To print the model parameters use the same print method as before.

# Prints isotherm parameters and model info
model_iso.print_info()

# We can calculate the loading at any pressure using the internal model by using the ``loading_at`` function.

# Returns the loading at 1 bar calculated with the model
model_iso.loading_at(1.0)

# Returns the loading in the range 0-1 bar calculated with the model
pressure = [0.1,0.5,1]
model_iso.loading_at(pressure)

# ## Plotting
#
# pyGAPS makes graphing both PointIsotherm and ModelIsotherm objects easy to facilitate
# visual observations, inclusion in publications and consistency. Plotting an isotherm is
# as simple as:

pg.plot_iso([isotherm, model_iso], branch='ads')

# Many settings can be specified to change the look and feel of the graphs. More 
# explanations can be found in the [manual](../manual/plotting.rst) and in 
# the [examples](../examples/plotting.ipynb) section.

StarcoderdataJupyterScriptsDedupFiltered