-
Notifications
You must be signed in to change notification settings - Fork 0
Profiling example #4
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
Merged
Merged
Changes from 8 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
a88da33
setup profiling examples
rogerkuou 1c795ea
add README
rogerkuou 289c0b1
update recursive script
rogerkuou 347acf7
update readme
rogerkuou 94fda9b
add dask method
rogerkuou 5b02a84
add dask example
rogerkuou 8637ba7
rename
rogerkuou e1f1712
add experiment results
rogerkuou b10b0b7
Apply suggestions from code review
rogerkuou 237fc82
Apply suggestions from code review
rogerkuou File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,55 @@ | ||
# Profiling example for Network unwrapping | ||
|
||
This is an example of how to perform profiling on the Arc Unwrapping algorithms. In this example we used the so-called "LAMBDA method" developed by TUDelft, and use a wrapper function in DePSI to call the unwrapping algorithm. | ||
|
||
- LAMBDA method: [LAMBDA.py](https://github.com/TUDelftGeodesy/DePSI_group/blob/dev/depsi/LAMBDA.py) (private repo) | ||
- Wrapper funtion `lambda_estimation`: [lambda_estimation](https://github.com/TUDelftGeodesy/DePSI_group/blob/dev/depsi/LAMBDA.py) (private repo) | ||
- Data needed for the example: [stm_amsterdam_173p.zarr](https://zenodo.org/records/15324181/files/stm_amsterdam_173p.zarr.zip?download=1) | ||
|
||
|
||
## File structure | ||
|
||
- lambda_unwrap.ipynb: Jupyter notebook for debugging and vislualization | ||
- lambda_unwrap.py: Python script for running the unwrapping algorithm in a recursive loop | ||
- lambda_unwrap_dask.ipynb: Jupyter notebook for debugging dask method | ||
- lambda_unwrap_dask.py: Python script for running the same unwrapping algorithm with dask databags | ||
|
||
## Profiling the unwrapping algorithm | ||
|
||
We use the `py-spy` package to profile the unwrapping algorithm. For example, we can use the following command to profile the unwrapping algorithm without dask | ||
|
||
### Loop method | ||
|
||
```sh | ||
py-spy record --output profile_loop_60pnts --idle --rate 5 --subprocesses --format speedscope python lambda_unwrap.py | ||
rogerkuou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
``` | ||
|
||
### Dask with `processes` schedular: | ||
rogerkuou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
In `lambda_unwrap_dask.py` configure: | ||
|
||
```py | ||
# Configure dask scheduler | ||
dask.config.set(scheduler="processes") | ||
``` | ||
|
||
```sh | ||
py-spy record --output profile_dask_60pnts_processes --idle --rate 5 --subprocesses --format speedscope python lambda_unwrap_dask.py | ||
rogerkuou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
``` | ||
|
||
### Dask with `threads` schedular: | ||
rogerkuou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```py | ||
# Configure dask scheduler | ||
dask.config.set(scheduler="threads") | ||
``` | ||
|
||
```sh | ||
py-spy record --output profile_dask_60pnts_threads --idle --rate 5 --subprocesses --format speedscope python lambda_unwrap_dask.py | ||
rogerkuou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
``` | ||
|
||
Then you can visualize the profile using the [`speedscope` web tool](https://www.speedscope.app/) | ||
rogerkuou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## Profiling results | ||
|
||
The results for 5 points, 24 points and 60 points can be found at: [this link](https://zenodo.org/records/15393928/files/experiments.zip) |
This file contains hidden or 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,317 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# An example to generate STM from dynamic estimation\n", | ||
"\n", | ||
"adapted from https://github.com/TUDelftGeodesy/DePSI_group/blob/dev/examples/notebooks/demo_dynamic_estimation.ipynb" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import numpy as np\n", | ||
"import xarray as xr\n", | ||
"import matplotlib.pyplot as plt\n", | ||
"\n", | ||
"# from depsi.LAMBDA import *\n", | ||
"from depsi.dynamic_estimation import lambda_estimation" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Set input parameters" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# set wavelength of Sentinel-1 (C-band)\n", | ||
"wavelength = 0.055465763 # m\n", | ||
"init_len = 50\n", | ||
"sigma_acc = 0.003 # m/yr^2\n", | ||
"L = 30/365\n", | ||
"\n", | ||
"# Initial gauss for the sigma of the unknown parameters\n", | ||
"sigma_offset = 0.001 #m\n", | ||
"sigma_vel = 0.0001 #m/yr\n", | ||
"sigma_h = 5 #m\n", | ||
"sigma_ther = 0.00005 #m/°C\n", | ||
"\n", | ||
"# the option for the LAMBDA method\n", | ||
"# method == 1: ILS with shrinking search\n", | ||
"# method == 2: Integer rounding\n", | ||
"# method == 3: Integer bootstrapping\n", | ||
"# method == 4: PAR\n", | ||
"# method == 5: ILS with Ratio Test\n", | ||
"method = 3" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Load the STM derived from PS selection" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Load all to memory\n", | ||
"stm = xr.open_zarr('../../data/stm_amsterdam_173p.zarr').compute()\n", | ||
"stm" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Choose the reference point" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Select the point with the smallest NMAD for initialization as the reference point\n", | ||
"nmad_init = np.array(stm['nmad_init'])\n", | ||
"ref_pnt_idx= int(np.argmin(nmad_init))\n", | ||
"ref_pnt_idx" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Define functions" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"def polynomial_fitting(x, y, degree=1):\n", | ||
" \"\"\"\n", | ||
" Perform polynomial fitting on the input data (x, y).\n", | ||
"\n", | ||
" Parameters:\n", | ||
" \n", | ||
" x : array_like\n", | ||
" Independent variable data points.\n", | ||
" y : array_like \n", | ||
" Dependent variable data points.\n", | ||
" degree: int\n", | ||
" Degree of the polynomial fit (default is 1 for linear).\n", | ||
"\n", | ||
" Returns:\n", | ||
" y_fitted : ndarray\n", | ||
" Fitted y values for the given x based on the polynomial fit.\n", | ||
" poly_fn : np.poly1d\n", | ||
" Polynomial function that represents the fit.\n", | ||
" coeffs : ndarray \n", | ||
" Coefficients of the fitted polynomial.\n", | ||
" \"\"\"\n", | ||
" # Validate inputs\n", | ||
" if len(x) != len(y):\n", | ||
" raise ValueError(\"Input arrays 'x' and 'y' must have the same length.\")\n", | ||
" if degree < 1:\n", | ||
" raise ValueError(\"Degree must be at least 1.\")\n", | ||
"\n", | ||
" # Perform polynomial fitting\n", | ||
" coeffs = np.polyfit(x, y, degree)\n", | ||
" poly_fn = np.poly1d(coeffs)\n", | ||
" y_fitted = poly_fn(x)\n", | ||
"\n", | ||
" return y_fitted, poly_fn, coeffs\n", | ||
"\n", | ||
"\n", | ||
"\n", | ||
"def NMAD_to_sigma_phase(nmad, method):\n", | ||
"\n", | ||
" \"\"\"\n", | ||
" Converts Normalized Median Absolute Deviation (NMAD) to the sigma of phase observations.\n", | ||
"\n", | ||
" This function uses an empirical cubic approximation (and is not based on physics):\n", | ||
" sigma = a + b*nmad + c*nmad**2 + d*nmad**3\n", | ||
"\n", | ||
" Parameters:\n", | ||
" nmad : array_like\n", | ||
" Normalized Median Absolute Deviation value.\n", | ||
" method : {'mean', 'mean_2_sigma'}\n", | ||
" Method used to compute sigma.\n", | ||
" \n", | ||
" Returns:\n", | ||
" sigma: ndarray\n", | ||
" Estimated sigma value.\n", | ||
" \"\"\"\n", | ||
" if method == 'mean':\n", | ||
" a, b, c, d = -0.0144869469, 2.00028682, -5.23271341, 21.1111801\n", | ||
" elif method == 'mean_2_sigma':\n", | ||
" a, b, c, d = 0.01907808, 1.2852969, 1.90052824, 11.60677721\n", | ||
" else:\n", | ||
" raise ValueError(\"Invalid method. Choose 'mean' or 'mean_2_sigma'.\")\n", | ||
"\n", | ||
" sigma = a + b*nmad + c*nmad**2 + d*nmad**3\n", | ||
" \n", | ||
" return sigma" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Perform unwrapping with lambda estimation" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# select the reference point\n", | ||
"stm_refpnt = stm.isel(space=ref_pnt_idx)\n", | ||
"\n", | ||
"# subset the data for debug\n", | ||
"NUM_POINTS = 5\n", | ||
"stm = stm.isel(space=range(5))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Initiate emty arrays to store results\n", | ||
rogerkuou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"x_hat = np.zeros((stm.sizes[\"space\"], 4))\n", | ||
"Q_xhat = np.zeros(( 4, 4, stm.sizes[\"space\"]))\n", | ||
"y_hats = np.zeros((stm.sizes[\"space\"], stm.sizes[\"time\"]))\n", | ||
"phs_unw_init = np.zeros((stm.sizes[\"space\"], stm.sizes[\"time\"]))\n", | ||
"\n", | ||
"\n", | ||
"# Loop over all points and perform phase unwrapping\n", | ||
"for pnt_id in range(stm.sizes[\"space\"]):\n", | ||
" # Select current point\n", | ||
" stm_1pnt = stm.isel(space=pnt_id)\n", | ||
"\n", | ||
" print(f\"{pnt_id}/{stm.sizes['space']}\")\n", | ||
"\n", | ||
" # Get the sigma for the arc with the NMAD from the incremental time series\n", | ||
" sigma_nmad_inc_i = NMAD_to_sigma_phase(\n", | ||
" stm_1pnt[\"nmad_inc_stm\"].data, \"mean_2_sigma\"\n", | ||
" )\n", | ||
" sigma_nmad_inc_j = NMAD_to_sigma_phase(\n", | ||
" stm_refpnt[\"nmad_inc_stm\"].data, \"mean_2_sigma\"\n", | ||
" )\n", | ||
" sigma_nmad_inc_arc = np.sqrt(\n", | ||
" np.square(sigma_nmad_inc_i) + np.square(sigma_nmad_inc_j)\n", | ||
" )\n", | ||
"\n", | ||
" # Compute arc phase\n", | ||
" phs_wrapped_arc = np.angle(\n", | ||
" stm_refpnt[\"sd_complex\"].data * stm_1pnt[\"sd_complex\"].data.conj()\n", | ||
" )\n", | ||
"\n", | ||
" # Compute 'mean' h2ph value for the arc (which we currently model as the average of the two time series)\n", | ||
" h2ph_arc = (stm_refpnt[\"h2ph_values\"].data + stm_1pnt[\"h2ph_values\"].data) / 2\n", | ||
"\n", | ||
" results = lambda_estimation(\n", | ||
" wavelength=wavelength,\n", | ||
" phs_wrapped=phs_wrapped_arc,\n", | ||
" sigma_phs_apri=sigma_nmad_inc_arc,\n", | ||
" years=stm_1pnt[\"years\"].data,\n", | ||
" h2ph_arc=h2ph_arc,\n", | ||
" temp=stm_1pnt[\"temperature\"].data,\n", | ||
" sigma_offset=sigma_offset,\n", | ||
" sigma_vel=sigma_vel,\n", | ||
" sigma_h=sigma_h,\n", | ||
" sigma_ther=sigma_ther,\n", | ||
" method=method,\n", | ||
" )\n", | ||
"\n", | ||
" # Store results\n", | ||
" x_hat[pnt_id, :] = results[0]\n", | ||
" Q_xhat[:, :, pnt_id] = results[1]\n", | ||
" y_hats[pnt_id, :] = results[2]\n", | ||
" phs_unw_init[pnt_id, :] = results[3]" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# For now, write x_hat and Q_xhat to npz files, since they so not fit in dimensions of an STM\n", | ||
"np.savez(\n", | ||
" \"./x_hat_Q_xhat.npz\",\n", | ||
" x_hat=x_hat,\n", | ||
" Q_xhat=Q_xhat,\n", | ||
")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Attach y_hats and phs_unw_init to the STM\n", | ||
"stm[\"y_hats\"] = ((\"space\", \"time\"), y_hats)\n", | ||
"stm[\"phs_unw_init\"] = ((\"space\", \"time\"), phs_unw_init)\n", | ||
"stm" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"stm.to_zarr(\n", | ||
" \"./stm_amsterdam_173p_init_unw.zarr\",\n", | ||
" mode=\"w\",\n", | ||
")" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "mobyle", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.11.6" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.