Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Devel #17

Merged
merged 19 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ repos:
- id: isort
name: isort (python)
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 24.2.0
rev: 24.3.0
hooks:
- id: black
language_version: python3.11
Expand Down
35 changes: 35 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
cff-version: 1.2.0
message: "If you use this software, please cite it as below."
type: software
authors:
- name: "PyRFU team"
- family-names: Richard
given-names: Louis
affiliation: IRF Uppsala, Sweden
orcid: "https://orcid.org/0000-0003-3446-7322"
- family-names: Khotyaintsev
given-names: Yuri
affiliation: IRF Uppsala, Sweden
orcid: "https://orcid.org/0000-0001-5550-3113"
- family-names: Vaivads
given-names: Andris
affiliation: KTH, Sweden
orcid: "https://orcid.org/0000-0003-1654-841X"
- family-names: Graham
given-names: Daniel
affiliation: IRF Uppsala, Sweden
orcid: "https://orcid.org/0000-0002-1046-746X"
- family-names: Norgren
given-names: Cecilia
affiliation: IRF Uppsala, Sweden
orcid: "https://orcid.org/0000-0002-6561-2337"
- family-names: Johlander
given-names: Andreas
affiliation: Swedish Defence Research Agency, Sweden
orcid: "https://orcid.org/0000-0001-7714-1870"
title: "pyrfu"
abstract: "An Open-Source Python Package for Advanced In-Situ Space Plasma Analysis."
license: MIT
doi: 10.5281/zenodo.10678695
url: "https://pyrfu.readthedocs.io/"
repository-code: 'https://github.com/louis-richard/irfu-python'
91 changes: 44 additions & 47 deletions docs/examples/01_mms/example_mms_b_e_j.ipynb

Large diffs are not rendered by default.

133 changes: 55 additions & 78 deletions docs/examples/01_mms/example_mms_ebfields.ipynb

Large diffs are not rendered by default.

174 changes: 61 additions & 113 deletions docs/examples/01_mms/example_mms_edr_signatures.ipynb

Large diffs are not rendered by default.

159 changes: 71 additions & 88 deletions docs/examples/01_mms/example_mms_ohmslaw.ipynb

Large diffs are not rendered by default.

329 changes: 161 additions & 168 deletions docs/examples/01_mms/example_mms_particle_distributions.ipynb

Large diffs are not rendered by default.

104 changes: 62 additions & 42 deletions docs/examples/01_mms/example_mms_reduced_ion_dist.ipynb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ filterwarnings = [
]

[tool.black]
py36 = true
target-version = ["py311"]
include = '\.pyi?$'
exclude = '''
/(
Expand Down
59 changes: 39 additions & 20 deletions pyrfu/mms/calculate_epsilon.py
Original file line number Diff line number Diff line change
@@ -1,50 +1,64 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Built-in imports
from typing import Optional

# 3rd party imports
import numpy as np
from scipy import constants
from xarray.core.dataarray import DataArray
from xarray.core.dataset import Dataset

# Local imports
from ..pyrf.resample import resample
from ..pyrf.ts_scalar import ts_scalar
from pyrfu.pyrf.resample import resample
from pyrfu.pyrf.ts_scalar import ts_scalar

__author__ = "Louis Richard"
__email__ = "[email protected]"
__copyright__ = "Copyright 2020-2023"
__copyright__ = "Copyright 2020-2024"
__license__ = "MIT"
__version__ = "2.4.2"
__version__ = "2.4.13"
__status__ = "Prototype"

q_e = constants.elementary_charge


def calculate_epsilon(vdf, model_vdf, n_s, sc_pot, **kwargs):
r"""Calculates epsilon parameter using model distribution.
def calculate_epsilon(
vdf: Dataset,
model_vdf: Dataset,
n_s: DataArray,
sc_pot: DataArray,
en_channels: Optional[list] = None,
) -> DataArray:
r"""Calculate epsilon parameter using model distribution.

Parameters
----------
vdf : xarray.Dataset
vdf : Dataset
Observed particle distribution (skymap).
model_vdf : xarray.Dataset
model_vdf : Dataset
Model particle distribution (skymap).
n_s : xarray.DataArray
n_s : DataArray
Time series of the number density.
sc_pot : xarray.DataArray
sc_pot : DataArray
Time series of the spacecraft potential.
**kwargs : dict
Keyword arguments.
en_channels : list, Optional
Set energy channels to integrate over [min max]; min and max between
must be between 1 and 32.

Returns
-------
epsilon : xarray.DataArray
DataArray
Time series of the epsilon parameter.

Other Parameters
----------------
en_channels : array_like
Set energy channels to integrate over [min max]; min and max between
must be between 1 and 32.
Raises
------
ValueError
If VDF and n_s have different times.
TypeError
If en_channels is not a list.


Examples
--------
Expand All @@ -53,7 +67,6 @@ def calculate_epsilon(vdf, model_vdf, n_s, sc_pot, **kwargs):
>>> eps = mms.calculate_epsilon(vdf, model_vdf, n_s, sc_pot, **options)

"""

# Resample sc_pot
sc_pot = resample(sc_pot, n_s)

Expand All @@ -78,7 +91,13 @@ def calculate_epsilon(vdf, model_vdf, n_s, sc_pot, **kwargs):
raise ValueError("vdf and moments have different times.")

# Default energy channels used to compute epsilon.
energy_range = kwargs.get("en_channels", [0, vdf.energy.shape[1]])
if en_channels is None:
energy_range = [0, vdf.energy.shape[1]]
elif isinstance(en_channels, list):
energy_range = en_channels
else:
raise TypeError("en_channels must be a list.")

int_energies = np.arange(energy_range[0], energy_range[1])

flag_same_e = np.sum(np.abs(vdf.attrs["energy0"] - vdf.attrs["energy1"])) < 1e-4
Expand Down
23 changes: 14 additions & 9 deletions pyrfu/mms/copy_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,28 @@
import json
import os
import shutil
from typing import Optional, Union

# Local imports
from .db_init import MMS_CFG_PATH
from .list_files import list_files
from pyrfu.mms.db_init import MMS_CFG_PATH
from pyrfu.mms.list_files import list_files

__author__ = "Louis Richard"
__email__ = "[email protected]"
__copyright__ = "Copyright 2020-2024"
__license__ = "MIT"
__version__ = "2.4.2"
__version__ = "2.4.13"
__status__ = "Prototype"


def copy_files(var, tint, mms_id, tar_path: str, data_path: str = ""):
r"""Copy files from local as defined in config.json to the target
path.
def copy_files(
var: dict,
tint: list,
mms_id: Union[int, str],
tar_path: str,
data_path: Optional[str] = "",
):
r"""Copy files from local as defined in config.json to the target path.

Parameters
----------
Expand All @@ -30,17 +36,16 @@ def copy_files(var, tint, mms_id, tar_path: str, data_path: str = ""):
* var["tmmode"] : data rate.
* var["lev"] : data level.
* var["dtype"] : data type.
tint : list of str
tint : list
Time interval.
mms_id : str or int
mms_id : int or str
Index of the spacecraft.
tar_path : str
Target path to put files.
data_path : str, Optional
Local path to MMS data. Default uses that provided in pyrfu.mms.config.json

"""

# Normalize the target path and make sure it exists.
tar_path = os.path.normpath(tar_path)
assert os.path.exists(tar_path), f"{tar_path} doesn't exist!!"
Expand Down
23 changes: 13 additions & 10 deletions pyrfu/mms/copy_files_ancillary.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,35 @@
# Built-in imports
import json
import os

# import subprocess
import shutil
from typing import Literal, Optional, Union

# Local imports
from .db_init import MMS_CFG_PATH
from .list_files_ancillary import list_files_ancillary
from pyrfu.mms.db_init import MMS_CFG_PATH
from pyrfu.mms.list_files_ancillary import list_files_ancillary

__author__ = "Louis Richard"
__email__ = "[email protected]"
__copyright__ = "Copyright 2020-2024"
__license__ = "MIT"
__version__ = "2.4.2"
__version__ = "2.4.13"
__status__ = "Prototype"


def copy_files_ancillary(product, tint, mms_id, tar_path: str, data_path: str = ""):
r"""Copy ancillary files from local as defined in config.json to
the target path.
def copy_files_ancillary(
product: Literal["predatt", "predeph", "defatt", "defeph"],
tint: list,
mms_id: Union[int, str],
tar_path: str,
data_path: Optional[str] = "",
):
r"""Copy ancillary files from local as defined in config.json to the target path.

Parameters
----------
product : {"predatt", "predeph", "defatt", "defeph"}
Ancillary type.
tint : list of str
tint : list
Time interval.
mms_id : str or int
Index of the spacecraft.
Expand All @@ -38,7 +42,6 @@ def copy_files_ancillary(product, tint, mms_id, tar_path: str, data_path: str =
Local path to MMS data. Default uses that provided in pyrfu.mms.config.json

"""

# Normalize the target path and make sure it exists.
tar_path = os.path.normpath(tar_path)
assert os.path.exists(tar_path), f"{tar_path} doesn't exist!!"
Expand Down
54 changes: 34 additions & 20 deletions pyrfu/mms/db_get_ts.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,27 @@
# Built-in imports
import json
import logging
from typing import Literal, Optional

# 3rd party imports
from xarray.core.dataarray import DataArray

from pyrfu.mms.db_init import MMS_CFG_PATH
from pyrfu.mms.get_data import (
_check_times,
_get_file_content_sources,
_list_files_sources,
)
from pyrfu.mms.get_ts import get_ts

# Local imports
from ..pyrf.ts_append import ts_append
from .db_init import MMS_CFG_PATH
from .get_data import _check_times, _get_file_content_sources, _list_files_sources
from .get_ts import get_ts
from pyrfu.pyrf.ts_append import ts_append

__author__ = "Louis Richard"
__email__ = "[email protected]"
__copyright__ = "Copyright 2020-2023"
__copyright__ = "Copyright 2020-2024"
__license__ = "MIT"
__version__ = "2.4.2"
__version__ = "2.4.13"
__status__ = "Prototype"

logging.captureWarnings(True)
Expand Down Expand Up @@ -43,13 +52,13 @@ def _tokenize(dataset_name):


def db_get_ts(
dataset_name,
cdf_name,
tint,
verbose: bool = True,
data_path: str = "",
source: str = "",
):
dataset_name: str,
cdf_name: str,
tint: list,
verbose: Optional[bool] = True,
data_path: Optional[str] = "",
source: Optional[Literal["default", "local", "sdc", "aws"]] = "default",
) -> DataArray:
r"""Get variable time series in the cdf file.

Parameters
Expand All @@ -58,35 +67,40 @@ def db_get_ts(
Name of the dataset.
cdf_name : str
Name of the target field in cdf file.
tint : array_like
tint : list
Time interval.
verbose : bool, Optional
Status monitoring. Default is verbose = True
data_path : str, Optional
Path of MMS data. Default uses `pyrfu.mms.mms_config.py`
source: {"local", "sdc", "aws"}, Optional
Ressource to fetch data from. Default uses default in `pyrfu/mms/config.json`
source: {"default", "local", "sdc", "aws"}, Optional
Resource to fetch data from. Default uses default in `pyrfu/mms/config.json`

Returns
-------
out : xarray.DataArray
DataArray
Time series of the target variable.

"""
Raises
------
FileNotFoundError
If no files are found for the dataset name.

"""
mms_id, var = _tokenize(dataset_name)

# Read the current version of the MMS configuration file
with open(MMS_CFG_PATH, "r", encoding="utf-8") as fs:
config = json.load(fs)

source = source if source else config.get("default")
source = source if source != "default" else config.get(source)

file_names, sdc_session, headers = _list_files_sources(
source, tint, mms_id, var, data_path
)

assert file_names, "No files found. Make sure that the data_path is correct"
if not file_names:
raise FileNotFoundError(f"No files found for {dataset_name}")

if verbose:
logging.info("Loading %s...", cdf_name)
Expand Down
Loading
Loading