diff --git a/.gitignore b/.gitignore index 2ac6e53..701f9ad 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ junit docs/build docs/source/generated docs/source/sg_execution_times.rst +docs-mk/site +docs-mk/docs/generated diff --git a/docs-mk/docs/about/index.md b/docs-mk/docs/about/index.md new file mode 100644 index 0000000..66415e7 --- /dev/null +++ b/docs-mk/docs/about/index.md @@ -0,0 +1,12 @@ +# About + +osipi is developed by the **Open Source Initiative for Perfusion Imaging (OSIPI)**, an initiative of the perfusion study group of the **International Society for Magnetic Resonance in Medicine (ISMRM)**. + +The osipi package structure and logic follow the lexicon defined by OSIPI, and wrap around selected implementations collected in the code contributions of OSIPI. + +## Scope + +osipi currently only includes methods for the dynamic contrast (DC) approach to perfusion MRI (DC-MRI, a unifying term for the separate fields DCE-MRI and DSC-MRI). In particular, arterial spin labelling (ASL) solutions are not currently included, but this may change in the future. + +!!! note "Future Updates" + The inclusion of arterial spin labelling (ASL) solutions may change in the future. diff --git a/docs-mk/docs/contribution/index.md b/docs-mk/docs/contribution/index.md new file mode 100644 index 0000000..d2d49e0 --- /dev/null +++ b/docs-mk/docs/contribution/index.md @@ -0,0 +1,84 @@ +# Developer Guide + +There are multiple ways to contribute to `osipi` and we welcome them all. `osipi` is a tool developed by the research community for the research community, and we are all responsible for ensuring it is as good as it can be. So, if you feel some part of it is not, fix it! + +The way to do this is by making a pull request on GitHub. If you are not familiar with GitHub pull requests, it is not as scary as it sounds. The simplest way is to find the file that you want to edit on GitHub in your browser, edit it manually and follow the prompts to create a fork and pull request. + +## How to Contribute Examples + +One way to contribute is by providing examples of how you used `osipi` for a specific task. These are usually real-world examples with a relevant aim, perhaps to derive some results that you have published. To package these up as an example, follow these steps: + +1. Code up your example in a single Python file in a narrative style, similar to a notebook. Have a look at the current examples to see how these need to be formatted, especially their docstrings, to make sure they show up properly on the website. +2. When you save your file, make sure the filename starts with *plot_*. +3. Then drop your file in the examples folder `osipi-docs-examples` in the appropriate subfolder. + +When the documentation is generated, your example will automatically appear in the examples gallery and also in the documentation of any function you are using in the example. + +## How to Contribute Documentation + +`osipi` is a user interface and for that reason good, clear and well-structured documentation is equally important as the quality of the functionality itself. We especially welcome suggestions for improving the documentation from end-users who are not necessarily contributing new code. You know best what works, and what doesn't. + +If you are a user of `osipi`, and some part of the documentation is not as clear as it can be, then submit your suggestions for improvement and make sure that the next person will not have to face the same issues. + +If you want to edit the documentation of a specific function, then you need to find the function in the osipi source code `osipi-src`. Find the function and edit the documentation string immediately below its definition. If you want to edit any other part of the documentation, find the appropriate file in the documentation source code `osipi-docs-source` and edit it there. + +## How to Contribute Tests + +Beyond documentation and functionality, solid testing is equally critical for ensuring long-term stability of a package. `osipi` uses a continuous integration model where all tests are run before each push to the central repository. This is important because often changes at one part of the code, even if tested well locally, can have unintended consequences at other parts. The testing prevents that these errors propagate and destabilize parts of the package. + +If you find a bug in any part of the code, this obviously points to a flaw in the code, but it also reveals a gap in the testing. It is critical when this happens that both the code AND the tests are reviewed to ensure that in future a scenario of this type is picked up during testing. + +The tests are defined in the folder `osipi-tests`. + +## How to Contribute Functionality + +OSIPI is always happy to receive new functionality for inclusion in the `osipi` package. This can be code that addresses a gap in the current functionality, or it can be code that improves the performance of a current implementation. Improvements can consist of extending the functionality (e.g. with new optional arguments), user friendliness or consistency, improvement of the accuracy or precision in the results, computation time, or platform independence, or improved documentation or code structure. + +Contribution of functionality generally proceeds in two steps. In the first step you submit your code to the primary *contributions* repository as explained in its [wiki](https://github.com/OSIPI/DCE-DSC-MRI_CodeCollection/wiki/How-to-contribute-code). The task force will catalogue your code in the contributions repository and test it as explained in the [guidance](https://github.com/OSIPI/DCE-DSC-MRI_CodeCollection/wiki/The-testing-approach). Afterwards, if it is found to address a gap in `osipi` and/or improve existing functionality, you will be invited to submit a pull request to `osipi` containing your contribution formatted as required by the package. + +While this is the general process, we accept there may be situations where a new submission to the contributions repository is overkill, for instance if your improvement concerns documentation only, or improvements in code structure or style. In that case a direct pull request to `osipi` may be acceptable - when in doubt please contact the OSIPI repository lead in the first instance to avoid unnecessary work. + +See the section on design principles below for general requirements from `osipi` code snippets. + +## How to Contribute Issues + +If you have a constructive suggestion for how `osipi` can be improved, but you are not able to address it yourself for some reason, it is still extremely helpful if you write this up as an issue so it can be picked up by others at a later stage. To write up an issue, go to the `osipi` repository on GitHub, select `issues` and write a new one. Make sure to provide sufficient detail so that others can understand and address the issue. + +## Design Principles + +### Style Guide + +`osipi` follows the [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html). This means especially also that we expect proper attention to error handling. Consider for instance what happens if a user calls your snippet using arguments of incorrect type or length. Will they get an appropriate error message that will help them identify and fix the error? + +### Package Structure + +The `osipi` documentation follows the structure of the OSIPI Lexicon exactly - see [here](https://osipi.github.io/OSIPI_CAPLEX/) for a detailed description of the Lexicon. + +From a user perspective, the package structure is a flat list of functions that can all be accessed as `osipi.some_function`. They are listed in the __init__ file of the package, directly under the folder `src\osipi`. For clarity, the code itself is organized into modules, but these may evolve over time and should not be accessed directly. Module names all start with an underscore `_module.py` to emphasize their private and transient nature. Equally, subfolders may be added in the future as the package grows. + + + +### Code Snippets + +`osipi` is a collection of *simple* code snippets following a *simple* functional programming paradigm (did you see how we said *simple* twice there?). Each code snippet is a Python function that takes OSIPI variables as arguments and returns other OSIPI variables as results. At this stage, we are *not* planning to include an object-oriented interface or internal logic as this reduces the modularity of the code snippets, reduces compatibility with other packages, and increases the overhead of learning how to use `osipi`. Therefore, all code contributions will essentially consist of a new function or an improvement of an existing function. + +Beyond the general requirements of the [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html), `osipi` requires that each new function is accompanied by an appropriate test in the tests folder, and that each function fully conforms to the Lexicon. In particular: + +1. Each function must be defined in the lexicon, and the docstring must include a reference section containing the following four items: + - Lexicon URL: webpage in the Lexicon where the function is defined. + - Lexicon code: machine-readable code identifying the entry in the Lexicon. + - OSIPI name: human-readable name for the function as defined in the Lexicon. + - Adapted from contribution: module.py in the original snippet in the code contribution repository +2. Each argument to the function as well as each return value *must* be defined in the Lexicon. The docstring of the function must provide the following data on each argument and return value: + - Python data type (include type hint in the function definition) + - Lexicon code: machine-readable code identifying the corresponding quantity in the Lexicon. + - OSIPI name: human-readable name for the quantity as defined in the Lexicon. +3. All arguments and return values must be provided in OSIPI units as defined in the Lexicon. +4. Arguments should be provided using OSIPI notation as defined in the Lexicon. +5. The docstring of the function must contain a self-contained code example that runs the function and illustrates the output. + +!!!note + If your function addresses entirely novel functionality or uses new variables that are not yet described in the Lexicon, then you should first contact the Lexicon maintainers and request that it is added as an entry to the Lexicon. Only afterwards can it be considered as a contribution to the `osipi` package. + +!!!note + The original [library for code contributions](https://github.com/OSIPI/DCE-DSC-MRI_CodeCollection/wiki/How-to-contribute-code) is less stringent as to code structure and documentation or testing requirements. However, it is nevertheless advisable to adhere to the same guidelines when submitting code to the original contributions repository as this will make it easier for testers to understand and run your code, and it will reduce the overhead on your part in rewriting the code diff --git a/docs-mk/docs/examples/README.md b/docs-mk/docs/examples/README.md new file mode 100644 index 0000000..7e371c4 --- /dev/null +++ b/docs-mk/docs/examples/README.md @@ -0,0 +1,5 @@ + +# Examples + + +### Illustrating common use cases of osipi. diff --git a/docs-mk/docs/examples/aif/README.md b/docs-mk/docs/examples/aif/README.md new file mode 100644 index 0000000..1e84a81 --- /dev/null +++ b/docs-mk/docs/examples/aif/README.md @@ -0,0 +1,3 @@ +************************ +Arterial Input Functions +************************ diff --git a/docs-mk/docs/examples/aif/plot_aif_parker.py b/docs-mk/docs/examples/aif/plot_aif_parker.py new file mode 100644 index 0000000..374cbce --- /dev/null +++ b/docs-mk/docs/examples/aif/plot_aif_parker.py @@ -0,0 +1,52 @@ +""" +====================================== +The Parker AIF - a play with variables +====================================== + +Simulating a Parker AIF with different settings. + +""" + +import matplotlib.pyplot as plt + +# %% +# Import necessary packages +import numpy as np +import osipi + +# %% +# Generate synthetic AIF with default settings and plot the result. + +# Define time points in units of seconds - in this case we use a time +# resolution of 0.5 sec and a total duration of 6 minutes. +t = np.arange(0, 6 * 60, 0.5) + +# Create an AIF with default settings +ca = osipi.aif_parker(t) + +# Plot the AIF over the full range +plt.plot(t, ca, "r-") +plt.plot(t, 0 * t, "k-") +plt.xlabel("Time (sec)") +plt.ylabel("Plasma concentration (mM)") +plt.show() + +# %% +# The bolus arrival time (BAT) defaults to 0s. What happens if we +# change it? Let's try, by changing it in steps of 30s: + +ca = osipi.aif_parker(t, BAT=0) +plt.plot(t, ca, "b-", label="BAT = 0s") +ca = osipi.aif_parker(t, BAT=30) +plt.plot(t, ca, "r-", label="BAT = 30s") +ca = osipi.aif_parker(t, BAT=60) +plt.plot(t, ca, "g-", label="BAT = 60s") +ca = osipi.aif_parker(t, BAT=90) +plt.plot(t, ca, "m-", label="BAT = 90s") +plt.xlabel("Time (sec)") +plt.ylabel("Plasma concentration (mM)") +plt.legend() +plt.show() + +# Choose the last image as a thumbnail for the gallery +# sphinx_gallery_thumbnail_number = -1 diff --git a/docs-mk/docs/examples/aif/plot_dummy.py b/docs-mk/docs/examples/aif/plot_dummy.py new file mode 100644 index 0000000..13cbac2 --- /dev/null +++ b/docs-mk/docs/examples/aif/plot_dummy.py @@ -0,0 +1,51 @@ +""" +============== +A dummy script +============== + +Dummy script to illustrate structure of examples folder +""" + +import matplotlib.pyplot as plt + +# %% +# Import necessary packages +import numpy as np +import osipi + +# %% +# Generate synthetic AIF with default settings and plot the result. + +# Define time points in units of seconds - in this case we use a time +# resolution of 0.5 sec and a total duration of 6 minutes. +t = np.arange(0, 6 * 60, 0.5) + +# Create an AIF with default settings +ca = osipi.aif_parker(t) + +# Plot the AIF over the full range +plt.plot(t, ca, "r-") +plt.plot(t, 0 * t, "k-") +plt.xlabel("Time (sec)") +plt.ylabel("Plasma concentration (mM)") +plt.show() + +# %% +# The bolus arrival time (BAT) defaults to 30s. What happens if we +# change it? Let's try, by changing it in steps of 30s: + +ca = osipi.aif_parker(t, BAT=0) +plt.plot(t, ca, "b-", label="BAT = 0s") +ca = osipi.aif_parker(t, BAT=30) +plt.plot(t, ca, "r-", label="BAT = 30s") +ca = osipi.aif_parker(t, BAT=60) +plt.plot(t, ca, "g-", label="BAT = 60s") +ca = osipi.aif_parker(t, BAT=90) +plt.plot(t, ca, "m-", label="BAT = 90s") +plt.xlabel("Time (sec)") +plt.ylabel("Plasma concentration (mM)") +plt.legend() +plt.show() + +# Choose the last image as a thumbnail for the gallery +# sphinx_gallery_thumbnail_number = -1 diff --git a/docs-mk/docs/examples/tissue/README.md b/docs-mk/docs/examples/tissue/README.md new file mode 100644 index 0000000..022965a --- /dev/null +++ b/docs-mk/docs/examples/tissue/README.md @@ -0,0 +1,3 @@ +********************* +Tissue concentrations +********************* diff --git a/docs-mk/docs/examples/tissue/plot_extended_tofts.py b/docs-mk/docs/examples/tissue/plot_extended_tofts.py new file mode 100644 index 0000000..f2df6fb --- /dev/null +++ b/docs-mk/docs/examples/tissue/plot_extended_tofts.py @@ -0,0 +1,57 @@ +""" +==================== +The Extended Tofts model +==================== + +Simulating tissue concentrations from extended Tofts model with different settings. +""" + +import matplotlib.pyplot as plt + +# %% +# Import necessary packages +import numpy as np +import osipi + +# %% +# Generate Parker AIF with default settings. + +# Define time points in units of seconds - in this case we use a time +# resolution of 1 sec and a total duration of 6 minutes. +t = np.arange(0, 6 * 60, 1) + +# Create an AIF with default settings +ca = osipi.aif_parker(t) + +# %% +# Plot the tissue concentrations for an extracellular volume fraction +# of 0.2 and 3 different plasma volumes of 0.05, 0.2 and 0.6 +Ktrans = 0.2 # in units of 1/min +ve = 0.2 # volume fraction between 0 and 1 +vp = [0.05, 0.2, 0.6] # volume fraction between 0 and 1 +ct = osipi.extended_tofts(t, ca, Ktrans, ve, vp[0]) +plt.plot(t, ct, "b-", label=f"vp = {vp[0]}") +ct = osipi.extended_tofts(t, ca, Ktrans, ve, vp[1]) +plt.plot(t, ct, "g-", label=f"vp = {vp[1]}") +ct = osipi.extended_tofts(t, ca, Ktrans, ve, vp[2]) +plt.plot(t, ct, "m-", label=f"vp = {vp[2]}") +plt.xlabel("Time (sec)") +plt.ylabel("Tissue concentration (mM)") +plt.legend() +plt.show() + +# %% +# Comparing different discretization methods for an extracellular +# volume fraction of 0.2, Ktrans of 0.2 /min and vp of 0.05 +ct = osipi.extended_tofts(t, ca, Ktrans, ve, vp[0]) # Defaults to Convolution +plt.plot(t, ct, "b-", label="Convolution") +ct = osipi.extended_tofts(t, ca, Ktrans, ve, vp[0], discretization_method="exp") +plt.plot(t, ct, "g-", label="Exponential Convolution") +plt.title(f"Ktrans = {Ktrans} /min") +plt.xlabel("Time (sec)") +plt.ylabel("Tissue concentration (mM)") +plt.legend() +plt.show() + +# Choose the last image as a thumbnail for the gallery +# sphinx_gallery_thumbnail_number = -1 diff --git a/docs-mk/docs/examples/tissue/plot_tofts.py b/docs-mk/docs/examples/tissue/plot_tofts.py new file mode 100644 index 0000000..d623da9 --- /dev/null +++ b/docs-mk/docs/examples/tissue/plot_tofts.py @@ -0,0 +1,57 @@ +""" +==================== +The Tofts model +==================== + +Simulating tissue concentrations from Tofts model with different settings. +""" + +import matplotlib.pyplot as plt + +# %% +# Import necessary packages +import numpy as np +import osipi + +# %% +# Generate Parker AIF with default settings. + +# Define time points in units of seconds - in this case we use a time +# resolution of 1 sec and a total duration of 6 minutes. +t = np.arange(0, 6 * 60, 1) + +# Create an AIF with default settings +ca = osipi.aif_parker(t) + +# %% +# Plot the tissue concentrations for an extracellular volume fraction +# of 0.2 and 3 different transfer rate constants of 0.05, 0.2 and 0.6 +# /min +Ktrans = [0.05, 0.2, 0.6] # in units of 1/min +ve = 0.2 # volume fraction between 0 and 1 +ct = osipi.tofts(t, ca, Ktrans=Ktrans[0], ve=ve) +plt.plot(t, ct, "b-", label=f"Ktrans = {Ktrans[0]} /min") +ct = osipi.tofts(t, ca, Ktrans[1], ve) +plt.plot(t, ct, "g-", label=f"Ktrans = {Ktrans[1]} /min") +ct = osipi.tofts(t, ca, Ktrans[2], ve) +plt.plot(t, ct, "m-", label=f"Ktrans = {Ktrans[2]} /min") +plt.xlabel("Time (sec)") +plt.ylabel("Tissue concentration (mM)") +plt.legend() +plt.show() + +# %% +# Comparing different discretization methods for an extracellular +# volume fraction of 0.2 and Ktrans of 0.2 /min +ct = osipi.tofts(t, ca, Ktrans=Ktrans[1], ve=ve) # Defaults to Convolution +plt.plot(t, ct, "b-", label="Convolution") +ct = osipi.tofts(t, ca, Ktrans=Ktrans[1], ve=ve, discretization_method="exp") +plt.plot(t, ct, "g-", label="Exponential Convolution") +plt.title(f"Ktrans = {Ktrans[1]} /min") +plt.xlabel("Time (sec)") +plt.ylabel("Tissue concentration (mM)") +plt.legend() +plt.show() + +# Choose the last image as a thumbnail for the gallery +# sphinx_gallery_thumbnail_number = -1 diff --git a/docs-mk/docs/img/osipi.png b/docs-mk/docs/img/osipi.png new file mode 100644 index 0000000..df995b2 Binary files /dev/null and b/docs-mk/docs/img/osipi.png differ diff --git a/docs-mk/docs/index.md b/docs-mk/docs/index.md new file mode 100644 index 0000000..50037d9 --- /dev/null +++ b/docs-mk/docs/index.md @@ -0,0 +1,27 @@ +# Osipi Documentation + +Welcome to the Osipi documentation! This guide is intended to help you get started with Osipi and provide the information you need to maximize its potential. + +## Warning + +!!! warning + `osipi` is developed in public but is a work in progress. This version contains mostly temporary placeholder functionality. + +## About Osipi + +`osipi` is the authoritative Python package for perfusion MRI. It is developed by the Open Source Initiative for Perfusion Imaging (OSIPI), which is a study group initiative of the International Society for Magnetic Resonance in Medicine (ISMRM). + +## Purpose + +The purpose of `osipi` is to standardize and streamline the use of perfusion MRI, ensuring consistency and reliability across different implementations and studies. The package follows the lexicon defined by OSIPI and integrates selected implementations from the original code contributions made by the OSIPI community. + + +Explore the documentation to learn more about how to use `osipi` and leverage its full capabilities for your perfusion MRI projects. + +## Sections + +- [User Guide](user-guide/index.md) +- [Contribution Guidelines](contribution/index.md) +- [References](references/index.md) +- [About](about/index.md) +- [Examples](examples/index.md) diff --git a/docs-mk/docs/references/index.md b/docs-mk/docs/references/index.md new file mode 100644 index 0000000..5e236db --- /dev/null +++ b/docs-mk/docs/references/index.md @@ -0,0 +1,10 @@ +# Reference + +This reference manual details all functions included in `osipi`, describing what they are and what they do. Documentation of individual functions contains self-contained example code that demonstrates basic usage of the function. + +The `osipi` package currently only includes methods for the dynamic contrast (DC) approach to perfusion MRI (DC-MRI, a unifying term for the separate fields DCE-MRI and DSC-MRI). In particular arterial spin labelling (ASL) solutions are not currently included, but may be added in the future. + +This reference guide, like the `osipi` package itself, adheres closely to the structure and language of the [OSIPI Lexicon](https://osipi.github.io/OSIPI_CAPLEX/). + +!!!warning + `osipi` is in development and this reference guide currently contains mainly empty placeholder entries. diff --git a/docs-mk/docs/references/models.md b/docs-mk/docs/references/models.md new file mode 100644 index 0000000..e69de29 diff --git a/docs-mk/docs/references/models/aif_models/aif_georgiou.md b/docs-mk/docs/references/models/aif_models/aif_georgiou.md new file mode 100644 index 0000000..6cf2330 --- /dev/null +++ b/docs-mk/docs/references/models/aif_models/aif_georgiou.md @@ -0,0 +1,3 @@ +# osipi.aif_georgiou + +::: osipi.aif_georgiou diff --git a/docs-mk/docs/references/models/aif_models/aif_parker.md b/docs-mk/docs/references/models/aif_models/aif_parker.md new file mode 100644 index 0000000..0d6307f --- /dev/null +++ b/docs-mk/docs/references/models/aif_models/aif_parker.md @@ -0,0 +1,20 @@ +# osipi.aif_parker + + +::: osipi.aif_parker + +## Example using `osipi.aif_parker` + +
+ + The Parker AIF - a play with variables +

+ + + The Parker AIF - a play with variables + + + +

+ +
diff --git a/docs-mk/docs/references/models/aif_models/aif_weinmann.md b/docs-mk/docs/references/models/aif_models/aif_weinmann.md new file mode 100644 index 0000000..8c6fa18 --- /dev/null +++ b/docs-mk/docs/references/models/aif_models/aif_weinmann.md @@ -0,0 +1,3 @@ +# osipi.aif_weinmann + +::: osipi.aif_weinmann diff --git a/docs-mk/docs/references/models/aif_models/index.md b/docs-mk/docs/references/models/aif_models/index.md new file mode 100644 index 0000000..adae95a --- /dev/null +++ b/docs-mk/docs/references/models/aif_models/index.md @@ -0,0 +1,5 @@ +# AIF models + +- [aif_parker](aif_parker.md) +- [aif_georgiou](aif_georgiou.md) +- [aif_weinmann](aif_weinmann.md) diff --git a/docs-mk/docs/references/models/index.md b/docs-mk/docs/references/models/index.md new file mode 100644 index 0000000..7cdc134 --- /dev/null +++ b/docs-mk/docs/references/models/index.md @@ -0,0 +1,8 @@ +# Models Overview + + +- [aif_parker](aif_models/aif_parker.md) +- [aif_georgiou](aif_models/aif_georgiou.md) +- [aif_weinmann](aif_models/aif_weinmann.md) +- [tofts](tissue_models/tofts.md) +- [extended_tofts](tissue_models/extended_tofts.md) diff --git a/docs-mk/docs/references/models/tissue_models/extended_tofts.md b/docs-mk/docs/references/models/tissue_models/extended_tofts.md new file mode 100644 index 0000000..b8b974c --- /dev/null +++ b/docs-mk/docs/references/models/tissue_models/extended_tofts.md @@ -0,0 +1,21 @@ +# osipi.extended_tofts + +::: osipi.extended_tofts + +## Example using `osipi.extended_tofts` + + + +
+ + The Extended Tofts model +

+ + + The Extended Tofts model + + + +

+ +
diff --git a/docs-mk/docs/references/models/tissue_models/index.md b/docs-mk/docs/references/models/tissue_models/index.md new file mode 100644 index 0000000..298b575 --- /dev/null +++ b/docs-mk/docs/references/models/tissue_models/index.md @@ -0,0 +1,3 @@ + +- [tofts](tofts.md) +- [extended_tofts](extended_tofts.md) diff --git a/docs-mk/docs/references/models/tissue_models/tofts.md b/docs-mk/docs/references/models/tissue_models/tofts.md new file mode 100644 index 0000000..0dcc063 --- /dev/null +++ b/docs-mk/docs/references/models/tissue_models/tofts.md @@ -0,0 +1,20 @@ +# osipi.tofts + +::: osipi.tofts + +## Example using `osipi.tofts` + + +
+ + The Tofts model +

+ + + The Tofts model + + + +

+ +
diff --git a/docs-mk/docs/stylesheets/extra.css b/docs-mk/docs/stylesheets/extra.css new file mode 100644 index 0000000..9409af0 --- /dev/null +++ b/docs-mk/docs/stylesheets/extra.css @@ -0,0 +1,36 @@ +.md-header__button.md-logo img{ +height: 50px; + +} + + +.model-table { + display: table; + width: 100%; + border-collapse: collapse; +} + +.model-row { + display: table-row; +} + +.model-name, .model-description { + display: table-cell; + padding: 10px; + vertical-align: top; +} + +.model-name { + width: 20%; + font-weight: bold; +} + +.model-description { + width: 80%; +} + +hr { + margin: 0; + border: 0; + border-top: 1px solid #ccc; +} diff --git a/docs-mk/docs/user-guide/gen_aif.md b/docs-mk/docs/user-guide/gen_aif.md new file mode 100644 index 0000000..8143615 --- /dev/null +++ b/docs-mk/docs/user-guide/gen_aif.md @@ -0,0 +1,37 @@ + + +## Generate an AIF and plot it: +``` py +import numpy as np +import matplotlib.pyplot as plt +import osipi + +t = np.arange(0, 6*60, 1) +ca = osipi.aif_parker(t) +plt.plot(t, ca) +plt.show() +``` + +## Generating a tissue concentration + +``` py +import numpy as np +import matplotlib.pyplot as plt +import osipi + +t = np.arange(0, 6*60, 1) +ca = osipi.aif_parker(t) +Ktrans = 0.6 +ve = 0.2 +ct = osipi.tofts(t, ca, Ktrans=Ktrans/60, ve=ve) +plt.plot(t, ct) +plt.show() +``` + +## Generating an MRI signal +!!! note "Coming Soon" + This section is under development and will be available soon. + +## Adding measurement error +!!! note "Coming Soon" + This section is under development and will be available soon. diff --git a/docs-mk/docs/user-guide/index.md b/docs-mk/docs/user-guide/index.md new file mode 100644 index 0000000..e21bfa6 --- /dev/null +++ b/docs-mk/docs/user-guide/index.md @@ -0,0 +1,17 @@ +# User Guide + +Welcome to the User Guide section. + +## Contents + +1. [Installing osipi](install.md) +2. [Simulating data](simulate.md) + - [Generating an AIF](simulate.md) + - [Generating a tissue concentration](simulate.md) + - [Generating an MRI signal](simulate.md) + - [Adding measurement error](simulate.md) +3. [Fitting data](simulate.md) + - [Signal to relaxation time](simulate.md) + - [Relaxation time to concentration](simulate.md) + - [Concentration to tissue parameters](simulate.md) + - [All in one go: signal to tissue parameters](simulate.md) diff --git a/docs-mk/docs/user-guide/install.md b/docs-mk/docs/user-guide/install.md new file mode 100644 index 0000000..6ee1bd8 --- /dev/null +++ b/docs-mk/docs/user-guide/install.md @@ -0,0 +1,13 @@ +# Installing osipi + +## Step 1: Prerequisites + +Ensure you have Python installed. You can download it from the [official Python website](https://www.python.org/downloads/). + +## Step 2: Install Using pip + +To install the package using `pip`, open your terminal and run the following command: + +``` +pip install osipi +``` diff --git a/docs-mk/docs/user-guide/simulate.md b/docs-mk/docs/user-guide/simulate.md new file mode 100644 index 0000000..b4b62bf --- /dev/null +++ b/docs-mk/docs/user-guide/simulate.md @@ -0,0 +1,5 @@ + +- [Generating an AIF](gen_aif.md#generating-an-aif) +- [Generating a Tissue Concentration](gen_aif.md#generating-a-tissue-concentration) +- [Generating an MRI Signal](gen_aif.md#generating-an-mri-signal) +- [Adding Measurement Error](gen_aif.md#adding-measurement-error) diff --git a/docs-mk/mkdocs.yml b/docs-mk/mkdocs.yml new file mode 100644 index 0000000..8c1e0b6 --- /dev/null +++ b/docs-mk/mkdocs.yml @@ -0,0 +1,109 @@ +site_name: '' +repo_url: https://github.com/OSIPI/pypi +theme: + name: material + logo: img/osipi.png + icon: + repo: fontawesome/brands/github + features: + - header.autohide + - navigation.tabs + - navigation.tabs.sticky + - navigation.instant + - navigation.instant.progress + - navigation.sections + - navigation.footer + - navigation.indexes + - toc.integrate + - navigation.top + - search.suggest + - search.highlight + - search.share + - content.tabs.link + - content.code.annotation + - content.code.copy + - content.code.select + - tables + language: en + palette: + - scheme: default + primary: teal + accent: purple + toggle: + icon: material/toggle-switch + name: Switch to dark mode + - scheme: slate + toggle: + icon: material/toggle-switch + name: Switch to dark mode + primary: teal + accent: lime + +plugins: + - mkdocstrings: + default_handler: python + - gallery: + examples_dirs: docs/examples + gallery_dirs: docs/generated/gallery + +extra_css: + - stylesheets/extra.css + +nav: + - Home: index.md + - User Guide: + - Overview: user-guide/index.md + - Installation: user-guide/install.md + - Simulating data: + - Overview: user-guide/simulate.md + - Simulate: user-guide/gen_aif.md + + - About: about/index.md + - Developer Guide: contribution/index.md + - References: + - references/index.md + - Index: + - references/models/index.md + - AIF models: + - references/models/aif_models/index.md + - osipi.aif_parker: references/models/aif_models/aif_parker.md + - osipi.aif_georgiou: references/models/aif_models/aif_georgiou.md + - osipi.aif_weinmann: references/models/aif_models/aif_weinmann.md + - Tissue models : + - references/models/tissue_models/index.md + - osipi.tofts: references/models/tissue_models/tofts.md + - osipi.extended_tofts: references/models/tissue_models/extended_tofts.md + + - Examples: generated/gallery + + +markdown_extensions: + - admonition + - codehilite + - footnotes + - meta + - toc: + permalink: true + - tables + - pymdownx.arithmatex + - pymdownx.betterem: + smart_enable: all + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - pymdownx.caret + - pymdownx.critic + - pymdownx.details + - pymdownx.inlinehilite + - pymdownx.magiclink + - pymdownx.mark + - pymdownx.smartsymbols + - pymdownx.superfences + - pymdownx.details + - pymdownx.tasklist: + custom_checkbox: true + - pymdownx.tilde + - pymdownx.tabbed: + alternate_style: true + - attr_list