-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* xdate works for overall series correlation * Added code for creating bins and dividing series into segments * Cleaning up and commenting related to xdate * series_corr works but is inefficient * WIP changes * Added comments, updated working jupyter notebook * Changes since start of fall semester * variance stabiliization produces accurate values * Unit tests for readers, summary, stats and tbrm * Added unit tests for detrend and chron * Added tests for chron_stabilized, series_corr and writers --------- Co-authored-by: Ifeoluwa Ale <[email protected]> Co-authored-by: cosimichele <[email protected]>
- Loading branch information
1 parent
8f29cbd
commit 8394f7c
Showing
33 changed files
with
4,551 additions
and
3,836 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
# dplPy Developer Instructions (in progress) | ||
|
||
Welcome to the dplPy developer manual. | ||
|
||
## Environment setup | ||
To contribute to dplpy, you will need to set up some tools | ||
|
||
### 1. GitHub setup | ||
|
||
#### 1.1 Create dplPy fork in github | ||
|
||
You will need your own copy of dplpy to work on the code. Go to the dplPy github page and click the fork button. Make sure the option to copy only the main branch is unchecked. | ||
|
||
|
||
#### 1.2 Create local repository | ||
In your local terminal, clone the fork to your computer using the commands shown below. Replace {your-user} with your github username. | ||
``` | ||
$ git clone https://github.com/{your-user}/OpenDendro/dplPy.git dplpy-{your-user} | ||
$ cd dplpy-{your-user} | ||
git remote add upstream https://github.com/OpenDendro/dplPy.git | ||
git fetch upstream | ||
``` | ||
|
||
This creates a github repository in dplPy-{your-user} on your computer and connects the repository to your fork, which is now connected to the main dplPy repository. | ||
|
||
#### 1.3 Create feature branch | ||
|
||
TBC | ||
|
||
|
||
### 2. Conda environment | ||
|
||
The packages required to run dplPy are all specified in environment.yml. | ||
|
||
#### 2.1\. Create your environment with the required packages installed. | ||
|
||
If you're using conda, run | ||
|
||
``` | ||
$ conda env create -f environment.yml | ||
``` | ||
|
||
If you're using mamba, run | ||
|
||
``` | ||
$ mamba env create -f environment.yml | ||
``` | ||
|
||
If prompted for permission to install requred packages, select y. | ||
|
||
#### 2.2\. Activate your environment. | ||
You will need to have the conda environment activated anytime you want to test code from the package. | ||
|
||
``` | ||
conda activate dplpy | ||
``` | ||
|
||
After running this command, you should see (dplpy) on the left of each new line in the terminal. | ||
|
||
#### 2.3\. Run unit and integration tests to ensure that installation was successful. | ||
TBA: Instructions for running tests | ||
|
||
### 3. IDE setup | ||
|
||
We recommend using VSCode for development. The following instructions show how to set up VSCode to recognize the conda environment and debug tests. | ||
|
||
#### 3.1\. Open the dplpy folder in VScode | ||
In VSCode, open the folder containing your local dplpy repository. If you followed the instructions above, this should be a folder named `dplpy-{your-github-username}`. Then, open the file `src/dplpy.py`. | ||
|
||
#### 3.2\. Change the python interpreter to use the conda environment's interpreter | ||
In the bottom corner of your IDE display, select the language interpreter. | ||
|
||
Choose the interpreter `Python 3.x ('dplpy')`, with a path that ends with `/envs/dplpy/python`. | ||
|
||
Now you should be able to run any python files within the currently open folder with the run button in VSCode, instead of running them through the terminal. | ||
|
||
Note: If the terminal is opened after the interpreter has been set to use the conda environment, conda activate dplpy will automatically be run and does not need to be run again. | ||
|
||
#### 3.3\. Set up unit testing tools | ||
|
||
Go to the testing tab (on the left side of the VSCode display). With your environment set. If the tests are not automatically discovered, open `.vscode/settings.json` and add the following lines inside the curly braces, so that your file looks like this: | ||
|
||
``` | ||
{ | ||
// any pre-existing configurations (DO NOT ADD THIS, THIS REPRESENTS ANYTHING ALREADY IN THE FILE) | ||
"python.testing.pytestArgs": [ | ||
"./src/unittests" | ||
], | ||
"python.testing.unittestEnabled": false, | ||
"python.testing.pytestEnabled": true | ||
} | ||
``` | ||
|
||
If `.vscode/settings.json` has not been created, create it and add the lines shown above. | ||
|
||
Go back to the testing tab and verify that the dplpy unit tests are showing. They should look like this: | ||
|
||
TBA: Image | ||
|
||
|
||
Run the tests by clicking the play button on src. | ||
|
||
|
||
## Overview of dplPy functions | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,4 +15,5 @@ dependencies: | |
- pip: | ||
- csaps | ||
- jupyterlab | ||
- notebook | ||
- notebook | ||
- pytest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,4 +2,6 @@ | |
|
||
__author__ = "Tyson Lee Swetnam" | ||
__email__ = "[email protected]" | ||
__version__ = "0.1" | ||
__version__ = "0.1" | ||
|
||
from src import dplpy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
from rbar import get_running_rbar, mean_series_intercorrelation | ||
from chron import chron | ||
import numpy as np | ||
import pandas as pd | ||
import warnings | ||
|
||
|
||
def chron_stabilized(rwi_data: pd.DataFrame, win_length=50, min_seg_ratio=0.33, biweight=True, running_rbar=False): | ||
if not isinstance(rwi_data, pd.DataFrame): | ||
raise TypeError("Expected data input to be a pandas dataframe, not " + str(type(rwi_data)) + ".") | ||
|
||
|
||
num_years = rwi_data.shape[0] | ||
|
||
if win_length > num_years: | ||
raise ValueError("Window length should not be greater than the number of rows in the dataset") | ||
|
||
if min_seg_ratio <= 0 or min_seg_ratio > 1: | ||
raise ValueError("min_seg_ratio cannot be <= 0 or > 1") | ||
|
||
if win_length < 0.3*num_years or win_length >= 0.5*num_years: | ||
warnings.warn("We recommend using a window length greater than 30%% but less than 50%% of the chronology length\n") | ||
|
||
print("Generating variance stabilized chronology...\n") | ||
|
||
# give rbar function a range of years (window length) to calculate rbar for | ||
# calculate rbar for that window, using either osborn's or frank's or 67spline | ||
# get rbar for each relevant segment of the dataframe | ||
|
||
|
||
mean_val = rwi_data.mean().mean() | ||
|
||
zero_mean_data = rwi_data - mean_val | ||
|
||
rbar_array = np.zeros(zero_mean_data.shape[0]) | ||
|
||
if win_length % 2 == 0: | ||
target = (win_length)/2 | ||
else: | ||
target = (win_length-1)/2 | ||
|
||
for i in range(num_years-win_length + 1): | ||
data_segment = zero_mean_data[i:i + win_length] | ||
if data_segment.shape[0] < win_length: | ||
continue | ||
target_index = int(i + target) | ||
rbar_array[target_index] = get_running_rbar(data_segment, min_seg_ratio) | ||
|
||
rbar_array = pad_rbar_array(rbar_array) | ||
|
||
reg_chron = chron(zero_mean_data, biweight=biweight, plot=False) | ||
|
||
mean_rwis = reg_chron["Mean RWI"].to_numpy() | ||
samp_deps = reg_chron["Sample depth"].to_numpy() | ||
denom = np.multiply(samp_deps-1, rbar_array) + 1 | ||
|
||
n_eff = np.minimum(np.divide(samp_deps, denom), samp_deps) | ||
rbar_const = mean_series_intercorrelation(zero_mean_data, "pearson", min_seg_ratio) | ||
stabilized_means = np.multiply(mean_rwis, np.sqrt(n_eff * rbar_const)) | ||
|
||
if running_rbar: | ||
stabilized_chron = pd.DataFrame(data={"Adjusted CRN": stabilized_means + mean_val, "Running rbar": rbar_array, "Sample depth": samp_deps}, index=reg_chron.index) | ||
else: | ||
stabilized_chron = pd.DataFrame(data={"Adjusted CRN": stabilized_means + mean_val, "Sample depth": samp_deps}, index=reg_chron.index) | ||
|
||
print("SUCCESS!\n") | ||
return stabilized_chron | ||
|
||
def pad_rbar_array(rbar_array): | ||
# double check that rbar cannot be 0 | ||
first = 0 | ||
first_valid = 0 | ||
for val in rbar_array: | ||
if val != 0 and not np.isnan(val): | ||
first = val | ||
break | ||
first_valid += 1 | ||
|
||
last = 0 | ||
last_valid = len(rbar_array) - 1 | ||
for val in np.flip(rbar_array): | ||
if val != 0 and not np.isnan(val): | ||
last = val | ||
break | ||
last_valid -= 1 | ||
|
||
rbar_array[:first_valid] = np.full(first_valid, first) #should be np.full(first_valid, 1) | ||
rbar_array[last_valid:] = np.full(len(rbar_array) - last_valid, last) #should be np.full(len(rbar_array) - last_valid, last) | ||
|
||
return rbar_array |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.