-
Notifications
You must be signed in to change notification settings - Fork 9
Added csm sandbox #134
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
Open
jrcain-usgs
wants to merge
7
commits into
DOI-USGS:main
Choose a base branch
from
jrcain-usgs:csm-sandbox
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Added csm sandbox #134
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
2bc67f6
Added csm sandbox
jrcain-usgs db0baf5
using non-naif values, added test slider
jrcain-usgs 2c422a3
better sliders, optical distortion x y z
jrcain-usgs 732802d
Exposure Ephem Center Time, sci notation sliders
jrcain-usgs e2d1b0a
add to toc
jrcain-usgs 121a6d2
Merge branch 'DOI-USGS:main' into csm-sandbox
jrcain-usgs 6d230e6
move data, download button, conda -> mamba, ipympl 0.9.6
jrcain-usgs 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,253 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# CSM Sandbox\n", | ||
"\n", | ||
"[Download This Notebook :octicons-file-code-16:](https://raw.githubusercontent.com/DOI-USGS/asc-public-docs/refs/heads/main/docs/getting-started/csm-stack/csm-sandbox.ipynb){ .md-button .md-button--primary } \n", | ||
"[Download Example Data :material-folder-arrow-down:](https://raw.githubusercontent.com/DOI-USGS/asc-public-docs/refs/heads/main/docs/getting-started/csm-stack/image-to-ground/image-to-ground.zip){ .md-button .md-button--primary }\n", | ||
"\n", | ||
"### Install Knoten & Prerequisites\n", | ||
"```sh\n", | ||
"mamba install -c conda-forge knoten=0.4 conda-forge matplotlib ipywidgets ipympl>=0.9.6\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Imports" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 1, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"%matplotlib widget\n", | ||
"import os # File Path Joining\n", | ||
"import json # Read ISD as python dictionary\n", | ||
"import copy # Important to be able to modify the ISD\n", | ||
"\n", | ||
"from knoten import csm # Knoten CSM\n", | ||
"\n", | ||
"import matplotlib.pyplot as plt # Math and Plotting Tools\n", | ||
"import ipywidgets as widgets\n", | ||
"from ipywidgets import Layout" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### Methods for reading/printing stats" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 2, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"def print_stats(dict, search_keys):\n", | ||
" for search_key in search_keys:\n", | ||
" print(f\"{search_key+\": \":<25}\" + str(dict[search_key]))\n", | ||
"\n", | ||
"def plot_footprint(lons, lats, aspect):\n", | ||
" plt.close()\n", | ||
" plt.rcParams[\"figure.figsize\"] = aspect\n", | ||
" plt.axes().set_aspect('equal','datalim')\n", | ||
" plt.plot(lons, lats)\n", | ||
" plt.xlabel(\"Longitude (deg)\")\n", | ||
" plt.ylabel(\"Latitude (deg)\")\n", | ||
" plt.title(\"CSM footprint\")\n", | ||
" plt.show()\n", | ||
"\n", | ||
"def plot_footprint_comparison(fp1, fp2, aspect):\n", | ||
" plt.clf() # clear previous figure\n", | ||
" plt.rcParams[\"figure.figsize\"] = aspect # set aspect ratio of plot\n", | ||
" plt.axes().set_aspect('equal','datalim') \n", | ||
" fp1_plot, = plt.plot(fp1[0], fp1[1], 'b') # Plot footprint 1 in blue\n", | ||
"\n", | ||
" margin = 0.001 # boundaries centered on footprint 1\n", | ||
" fp1_lim_x = plt.xlim()\n", | ||
" fp1_lim_y = plt.ylim()\n", | ||
" fp1_lim_x = (fp1_lim_x[0] - margin, fp1_lim_x[1] + margin)\n", | ||
" fp1_lim_y = (fp1_lim_y[0] - margin, fp1_lim_y[1] + margin)\n", | ||
"\n", | ||
" fp2_plot, = plt.plot(fp2[0], fp2[1], 'r') # Plot footprint 2 in red\n", | ||
" plt.title(\"Original vs. Modified Footprint\") # Title and axis labels\n", | ||
" plt.xlabel(\"Longitude (deg)\")\n", | ||
" plt.ylabel(\"Latitude (deg)\")\n", | ||
" fp1_plot.set_label(fp1[2]) # Labels/Legend\n", | ||
" fp2_plot.set_label(fp2[2])\n", | ||
" plt.legend()\n", | ||
" plt.xlim(fp1_lim_x) # Set Size\n", | ||
" plt.ylim(fp1_lim_y)\n", | ||
" plt.show() # Show plot" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### Stats/Footprint of original ISD" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"focal_length_model: {'focal_length': 352.9271664}\n", | ||
"detector_center: {'line': 0.430442527, 'sample': 2542.96099}\n", | ||
"optical_distortion: {'radial': {'coefficients': [-0.0073433925920054505, 2.8375878636241697e-05, 1.2841989124027099e-08]}}\n", | ||
"center_ephemeris_time: 297088762.2425226\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"# Load Dict from JSON-style ISD File\n", | ||
"data_dir = 'image-to-ground'\n", | ||
"isd_file = os.path.join(data_dir, 'isd_file.json')\n", | ||
"\n", | ||
"with open(isd_file) as json_file:\n", | ||
" isd_dict = json.load(json_file)\n", | ||
"\n", | ||
"# Print selected values from ISD\n", | ||
"print_stats(isd_dict, ('focal_length_model', 'detector_center', 'optical_distortion', 'center_ephemeris_time'))\n", | ||
"\n", | ||
"# Create Camera Model\n", | ||
"camera = csm.create_csm(isd_file)\n", | ||
"\n", | ||
"# Get the footprint using the model\n", | ||
"boundary = csm.generate_boundary((isd_dict[\"image_lines\"], isd_dict[\"image_samples\"]))\n", | ||
"lons, lats, alts = csm.generate_latlon_boundary(camera, boundary)\n", | ||
"\n", | ||
"# # This line can plot the footprint of the original ISD\n", | ||
"# plot_footprint(lons, lats, [5,1])" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### Modify ISD/write to file" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"Adjust Sliders to add or subtract from the values at the following ISD Keys:\n" | ||
] | ||
}, | ||
{ | ||
"data": { | ||
"application/vnd.jupyter.widget-view+json": { | ||
"model_id": "99f757a292504ab19d2b8db31cbd9cd3", | ||
"version_major": 2, | ||
"version_minor": 0 | ||
}, | ||
"text/plain": [ | ||
"interactive(children=(FloatSlider(value=0.0, description='Focal Length', layout=Layout(width='600px'), max=0.2…" | ||
] | ||
}, | ||
"metadata": {}, | ||
"output_type": "display_data" | ||
} | ||
], | ||
"source": [ | ||
"# clear the plot from any previous footprints/plots\n", | ||
"plt.close()\n", | ||
"\n", | ||
"# Copy the ISD Dictionary, we will modify it and compare to the original.\n", | ||
"isd_dict_mod = copy.deepcopy(isd_dict)\n", | ||
"\n", | ||
"print('Adjust Sliders to add or subtract from the values at the following ISD Keys:')\n", | ||
"\n", | ||
"# Slider Widgets\n", | ||
"wide_lay = Layout(width='600px')\n", | ||
"wide_desc = {'description_width': '150px'}\n", | ||
"@widgets.interact(\n", | ||
" fl_add=widgets.FloatSlider(min=-0.25, max=.25, step=0.001, description='Focal Length', layout=wide_lay, style=wide_desc), \n", | ||
" dcl_add=widgets.FloatSlider(min=-4, max=4, step=0.05, description='Detector Center Line', layout=wide_lay, style=wide_desc),\n", | ||
" dcs_add=widgets.FloatSlider(min=-2.5, max=2.5, step=0.02, description='Detector Center Sample', layout=wide_lay, style=wide_desc),\n", | ||
" opt_x=widgets.FloatSlider(min=-0.001, max=0.001, step=0.00001, description='Optical Distortion X', layout=wide_lay, style=wide_desc, readout_format='.5f'),\n", | ||
" opt_y=widgets.FloatSlider(min=-2e-6, max=2e-6, step=2e-8, description='Optical Distortion Y', layout=wide_lay, style=wide_desc, readout_format='.1e'),\n", | ||
" opt_z=widgets.FloatSlider(min=-1e-8, max=1e-8, step=1e-10, description='Optical Distortion Z', layout=wide_lay, style=wide_desc, readout_format='.1e'),\n", | ||
" ect_add=widgets.FloatSlider(min=-1e-2, max=1e-2, step=1e-4, description='Exposure (Center) Time', layout=wide_lay, style=wide_desc, readout_format='.4f')\n", | ||
" )\n", | ||
"# This function executed whenever one of the slider widgets is adjusted\n", | ||
"def exec_widget_function(fl_add, dcl_add, dcs_add, opt_x, opt_y, opt_z, ect_add):\n", | ||
"\n", | ||
" # If you're curious where the ISD values came from, \n", | ||
" # Detector Center was from NAIF Boresight Line/Sample\n", | ||
" # Optical Distortion was from NAIF OD_K\n", | ||
" # ISIS uses the NAIF Keywords, but Knoten CSM uses other derived ISD values.\n", | ||
"\n", | ||
" new_values = {\n", | ||
" 'focal_length_model': {'focal_length': 352.9271664 + fl_add},\n", | ||
" 'detector_center': {'line': 0.430442527 + dcl_add, 'sample': 2542.96099 + dcs_add},\n", | ||
" 'optical_distortion': {'radial': {'coefficients': [-0.007343 + opt_x, 2.838e-05 + opt_y, 1.284e-08 + opt_z]}},\n", | ||
" 'center_ephemeris_time': 297088762.2425226 + ect_add\n", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this slider is good, but this is changing there center time, not exposure time. Exposure time is part of the Additionally, might be worth adding sliders or changing values in |
||
" }\n", | ||
"\n", | ||
" # Modify Values in Dictionary\n", | ||
" for key,value in new_values.items(): \n", | ||
" isd_dict_mod[key] = new_values[key]\n", | ||
"\n", | ||
" # Write ISD to file\n", | ||
" isd_file_mod = os.path.join(data_dir, 'isd_file_mod.json')\n", | ||
" with open(isd_file_mod, 'w') as json_file:\n", | ||
" json.dump(isd_dict_mod, json_file, indent=4)\n", | ||
"\n", | ||
" print_stats(isd_dict_mod, ('focal_length_model', 'detector_center', 'optical_distortion', 'center_ephemeris_time'))\n", | ||
"\n", | ||
" # Create Camera Model\n", | ||
" camera = csm.create_csm(isd_file_mod)\n", | ||
"\n", | ||
" # Get the footprint using the model\n", | ||
" boundary_mod = csm.generate_boundary((isd_dict_mod[\"image_lines\"], isd_dict_mod[\"image_samples\"]))\n", | ||
" lons_mod, lats_mod, alts_mod = csm.generate_latlon_boundary(camera, boundary_mod)\n", | ||
"\n", | ||
" # Plot it\n", | ||
" plot_footprint_comparison((lons, lats, \"Original\"),(lons_mod, lats_mod, \"Modified\"), [7,3])" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "knoten", | ||
"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.12.7" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
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
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
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
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
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
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed this ISD was 1x1 pixel. It would be better to do something that is full sample length with cropped lines. Especially since this is a CTX camera.