PyThea 0.9.0__tar.gz → 0.10.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {PyThea-0.9.0 → pythea-0.10.0}/CHANGELOG.md +35 -0
- {PyThea-0.9.0/PyThea.egg-info → pythea-0.10.0}/PKG-INFO +3 -3
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/PyThea_app.py +98 -51
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/_version.py +2 -2
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/callbacks.py +2 -1
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/geometrical_models.py +12 -6
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/modules.py +33 -36
- pythea-0.10.0/PyThea/sunpy_dev/extern/sunkit_instruments/aia/utils.py +14 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/sunpy_dev/map/maputils.py +26 -12
- pythea-0.10.0/PyThea/test/Pythea_test.py +24 -0
- pythea-0.10.0/PyThea/test/__init__.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/utils.py +102 -21
- {PyThea-0.9.0 → pythea-0.10.0/PyThea.egg-info}/PKG-INFO +3 -3
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea.egg-info/SOURCES.txt +2 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea.egg-info/requires.txt +2 -2
- {PyThea-0.9.0 → pythea-0.10.0}/environment.yml +2 -2
- {PyThea-0.9.0 → pythea-0.10.0}/requirements.txt +2 -2
- PyThea-0.9.0/PyThea/test/Pythea_test.py +0 -8
- {PyThea-0.9.0 → pythea-0.10.0}/LICENSE.md +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/MANIFEST.in +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/__init__.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/config/__init__.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/config/app_styles.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/config/config_sliders.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/config/selected_bodies.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/config/selected_imagers.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/data/__init__.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/data/sample_data.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/extensions/LICENSE_gcs_python.md +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/extensions/__init__.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/extensions/buttons.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/pythea_cli.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/sunpy_dev/__init__.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/sunpy_dev/extern/__init__.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/sunpy_dev/extern/sunkit_instruments/__init__.py +0 -0
- {PyThea-0.9.0/PyThea/sunpy_dev/extern/sunkit_instruments/lasco → pythea-0.10.0/PyThea/sunpy_dev/extern/sunkit_instruments/aia}/__init__.py +0 -0
- {PyThea-0.9.0/PyThea/sunpy_dev/extern/sunkit_instruments/stereo → pythea-0.10.0/PyThea/sunpy_dev/extern/sunkit_instruments/lasco}/__init__.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/sunpy_dev/extern/sunkit_instruments/lasco/utils.py +0 -0
- {PyThea-0.9.0/PyThea/sunpy_dev/map → pythea-0.10.0/PyThea/sunpy_dev/extern/sunkit_instruments/stereo}/__init__.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/sunpy_dev/extern/sunkit_instruments/stereo/utils.py +0 -0
- {PyThea-0.9.0/PyThea/test → pythea-0.10.0/PyThea/sunpy_dev/map}/__init__.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/test/conftest.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/test/test_geometrical_models.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/test/test_imports.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/test/test_remote_clients.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/test/test_utils.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea/version.py +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea.egg-info/.DS_Store +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea.egg-info/dependency_links.txt +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea.egg-info/entry_points.txt +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea.egg-info/not-zip-safe +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/PyThea.egg-info/top_level.txt +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/README.md +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/README_pypi.md +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/pyproject.toml +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/setup.cfg +0 -0
- {PyThea-0.9.0 → pythea-0.10.0}/setup.py +0 -0
|
@@ -1,3 +1,38 @@
|
|
|
1
|
+
# v0.10.0 (17-April-2024)
|
|
2
|
+
|
|
3
|
+
## Features
|
|
4
|
+
- Option added to choose the step for Running Difference or the background image for the Base Difference image processing.
|
|
5
|
+
- Fetures added in the app to plot limb or meridians from different observers and grid.
|
|
6
|
+
- Feture added in the app for manual change of the images colorbar limits.
|
|
7
|
+
- Feture added in the app to use median filter images processing.
|
|
8
|
+
- Tests added: A test to verify the existence of Pythea's database directory
|
|
9
|
+
|
|
10
|
+
## Major Changes
|
|
11
|
+
- Updates sunpy dependencies to sunpy 5.1.2
|
|
12
|
+
|
|
13
|
+
## Minor Changes
|
|
14
|
+
- Improvements on the pipeline of image download and processing in the app.
|
|
15
|
+
- Improvements and simplifications on the figures production in the app.
|
|
16
|
+
- Values of the colormap limits in the app are stored and are reused when changing the imager.
|
|
17
|
+
|
|
18
|
+
## Bug Fixes
|
|
19
|
+
- Fixes a bug with test_database_dir_exists.
|
|
20
|
+
- Fixes a bug when corrupted fits files loaded and imager load skipped.
|
|
21
|
+
- Fixes a bug with AIA visuallization from missing date_average.
|
|
22
|
+
- Fixes a bug with supplementary imaging selection.
|
|
23
|
+
|
|
24
|
+
# v0.9.1 (5-March-2024)
|
|
25
|
+
|
|
26
|
+
## Features
|
|
27
|
+
- A utility added to load the json fitting files
|
|
28
|
+
|
|
29
|
+
## Minor Changes
|
|
30
|
+
- Simplifies the code structure for loading the fitting files in the app
|
|
31
|
+
|
|
32
|
+
## Bug Fixes
|
|
33
|
+
- Fixes a bug when passing no maps in maputils
|
|
34
|
+
- Fixes a bug when corrupted fits files loaded and imager load skipped
|
|
35
|
+
|
|
1
36
|
# v0.9.0 (8-Feb-2024)
|
|
2
37
|
|
|
3
38
|
## Features
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyThea
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.0
|
|
4
4
|
Summary: PyThea: A software package to reconstruct the 3D structure of CMEs and shock waves
|
|
5
5
|
Home-page: https://github.com/AthKouloumvakos/PyThea
|
|
6
6
|
Author: Athanasios Kouloumvakos
|
|
@@ -27,8 +27,8 @@ Requires-Dist: aiapy
|
|
|
27
27
|
Requires-Dist: astropy
|
|
28
28
|
Requires-Dist: astroquery
|
|
29
29
|
Requires-Dist: numexpr
|
|
30
|
-
Requires-Dist: sunpy==
|
|
31
|
-
Requires-Dist: parfive==1.
|
|
30
|
+
Requires-Dist: sunpy==5.1.2
|
|
31
|
+
Requires-Dist: parfive==2.1.0
|
|
32
32
|
Requires-Dist: pooch
|
|
33
33
|
Requires-Dist: matplotlib
|
|
34
34
|
Requires-Dist: seaborn
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
from copy import copy
|
|
22
|
+
|
|
21
23
|
import astropy.units as u
|
|
22
24
|
import numpy as np
|
|
23
25
|
import stqdm # See also https://github.com/tqdm/tqdm
|
|
@@ -29,12 +31,12 @@ from PyThea.callbacks import load_or_delete_fittings
|
|
|
29
31
|
from PyThea.config import (app_styles, config_sliders, selected_bodies,
|
|
30
32
|
selected_imagers)
|
|
31
33
|
from PyThea.geometrical_models import ellipsoid, gcs, spheroid
|
|
32
|
-
from PyThea.modules import (date_and_event_selection,
|
|
34
|
+
from PyThea.modules import (date_and_event_selection, figure_streamlit,
|
|
35
|
+
final_parameters_gmodel,
|
|
33
36
|
fitting_and_slider_options_container,
|
|
34
|
-
fitting_sliders
|
|
35
|
-
from PyThea.sunpy_dev.map.maputils import get_closest
|
|
36
|
-
from PyThea.utils import (download_fits,
|
|
37
|
-
plot_bodies, plot_fitting_model,
|
|
37
|
+
fitting_sliders)
|
|
38
|
+
from PyThea.sunpy_dev.map.maputils import get_closest, maps_clims
|
|
39
|
+
from PyThea.utils import (download_fits, model_fittings, plot_fitting_model,
|
|
38
40
|
single_imager_maps_process)
|
|
39
41
|
from PyThea.version import version
|
|
40
42
|
|
|
@@ -185,24 +187,58 @@ def run():
|
|
|
185
187
|
if 'imagers_list_' not in st.session_state:
|
|
186
188
|
# imagers_list_ is used later when we download or filter the images
|
|
187
189
|
st.session_state['imagers_list_'] = []
|
|
188
|
-
image_mode = procoption_container.selectbox('Map
|
|
190
|
+
image_mode = procoption_container.selectbox('Map Sequence Processing',
|
|
189
191
|
options=['Running Diff.', 'Base Diff.', 'Plain'], key='image_mode',
|
|
190
|
-
on_change=delete_from_state,
|
|
192
|
+
on_change=delete_from_state,
|
|
193
|
+
kwargs={'vars': ['map', 'imagers_list_', 'clim', 'clim_manual_low', 'clim_manual_high']})
|
|
194
|
+
if image_mode in ['Running Diff.', 'Base Diff.']:
|
|
195
|
+
diff_value = procoption_container.number_input('Select Step/Image for Running/Base Diff.', 1, 5, key='diff_value',
|
|
196
|
+
on_change=delete_from_state,
|
|
197
|
+
kwargs={'vars': ['map', 'imagers_list_', 'clim', 'clim_manual_low', 'clim_manual_high']})
|
|
198
|
+
else:
|
|
199
|
+
diff_value = None
|
|
200
|
+
|
|
201
|
+
procoption_container.number_input('Median Filter', 1, 6, 1, 1, key='images_median_filter')
|
|
191
202
|
|
|
192
203
|
with st.sidebar.expander('Plot/View Options'):
|
|
193
204
|
plotviewopt_container = st.container()
|
|
194
|
-
|
|
205
|
+
plotviewopt_container.checkbox('Clip plot on image limits', value=True, key='clip_model')
|
|
195
206
|
plt_supp_imagers = plotviewopt_container.checkbox('Supplementary Imaging', value=False)
|
|
196
|
-
|
|
197
|
-
if star_field:
|
|
198
|
-
|
|
199
|
-
|
|
207
|
+
plotviewopt_container.checkbox('View Bodies or s/c', key='star_field')
|
|
208
|
+
if st.session_state.star_field:
|
|
209
|
+
plotviewopt_container.multiselect('Select Bodies', options=selected_bodies.bodies_dict.keys(),
|
|
210
|
+
default=['Mercury', 'Venus', 'Jupiter'],
|
|
211
|
+
key='bodies_list')
|
|
212
|
+
plotviewopt_container.checkbox('View Limb and Meridians', key='plot_solar_reference_lines_')
|
|
213
|
+
if st.session_state.plot_solar_reference_lines_:
|
|
214
|
+
markdown = '''
|
|
215
|
+
**Limb**: plots the solar limb as observed # noqa
|
|
216
|
+
for the selected observers. # noqa
|
|
217
|
+
**Central Meridian**: plots the central meridian # noqa
|
|
218
|
+
observed for the selected observers. # noqa
|
|
219
|
+
**CR Meridan+Equator**: plots the primary meridian # noqa
|
|
220
|
+
and equator of Carrington coordinate system. # noqa
|
|
221
|
+
'''.strip()
|
|
222
|
+
plotviewopt_container.selectbox('Select plot option',
|
|
223
|
+
options=['Limb from Obs.', 'Central Meridian from Obs.', 'Carr. Prime Meridian+Solar Equator',
|
|
224
|
+
'Stonyhurst Grid', 'Carrington Grid'],
|
|
225
|
+
help=markdown,
|
|
226
|
+
key='plot_solar_reference_lines_mode')
|
|
227
|
+
disabled = False if st.session_state.plot_solar_reference_lines_mode in ['Limb from Obs.', 'Central Meridian from Obs.'] else True
|
|
228
|
+
plotviewopt_container.multiselect('Select Bodies',
|
|
229
|
+
label_visibility='collapsed',
|
|
230
|
+
options=selected_bodies.bodies_dict.keys(),
|
|
231
|
+
default=['Earth'], disabled=disabled,
|
|
232
|
+
key='plot_solar_reference_lines_bodies_list')
|
|
200
233
|
|
|
201
234
|
#############################################################
|
|
202
235
|
# Download and Process the Images
|
|
203
236
|
# This part runs only if the map_ doesn't exits or the session_state.map_ does not contain all the imagers requested
|
|
204
237
|
imager_added = list(set(imagers_list) - set(st.session_state['imagers_list_']))
|
|
205
238
|
imager_removed = list(set(st.session_state['imagers_list_']) - set(imagers_list))
|
|
239
|
+
if 'map_colormap_limits' not in st.session_state:
|
|
240
|
+
st.session_state['map_colormap_limits'] = {}
|
|
241
|
+
|
|
206
242
|
if 'map_' not in st.session_state or imager_added != []:
|
|
207
243
|
st.session_state.map_ = {} if 'map_' not in st.session_state else st.session_state.map_
|
|
208
244
|
st.session_state.map = {} if 'map' not in st.session_state else st.session_state.map
|
|
@@ -213,20 +249,25 @@ def run():
|
|
|
213
249
|
if imager not in st.session_state.map_:
|
|
214
250
|
st.session_state.map_[imager] = download_fits(st.session_state.date_process,
|
|
215
251
|
imager, time_range=imaging_time_range)
|
|
252
|
+
st.session_state.map_[imager] = single_imager_maps_process(st.session_state.map_[imager],
|
|
253
|
+
**selected_imagers.imager_dict[imager][1],
|
|
254
|
+
skip='sequence_processing')
|
|
216
255
|
processed_images = single_imager_maps_process(st.session_state.map_[imager],
|
|
256
|
+
skip=['filter', 'prepare'],
|
|
217
257
|
image_mode=image_mode,
|
|
218
|
-
|
|
258
|
+
diff_num=diff_value)
|
|
219
259
|
if processed_images != []:
|
|
220
260
|
st.session_state.map[imager] = processed_images
|
|
261
|
+
st.session_state.map_colormap_limits[imager] = maps_clims(st.session_state.map[imager])
|
|
221
262
|
else:
|
|
222
263
|
st.session_state.imagers_list_.remove(imager)
|
|
264
|
+
st.session_state.map_colormap_limits.pop(imager, None)
|
|
265
|
+
|
|
223
266
|
if imager_removed != []:
|
|
224
267
|
st.session_state['imagers_list_'] = imagers_list
|
|
225
268
|
for imager in imager_removed:
|
|
226
269
|
st.session_state.map_.pop(imager, None)
|
|
227
270
|
|
|
228
|
-
maps_clims(st, st.session_state.imagers_list_)
|
|
229
|
-
|
|
230
271
|
if not st.session_state.imagers_list_:
|
|
231
272
|
st.error('No images have been downloaded or processed.') # TODO: Explain better
|
|
232
273
|
st.stop()
|
|
@@ -236,7 +277,8 @@ def run():
|
|
|
236
277
|
st.markdown('### Multi-viewpoint imaging')
|
|
237
278
|
col1, col2 = st.columns((1, 3))
|
|
238
279
|
imager_select = col1.selectbox('Select an imager',
|
|
239
|
-
options=st.session_state.imagers_list_
|
|
280
|
+
options=st.session_state.imagers_list_,
|
|
281
|
+
on_change=delete_from_state, kwargs={'vars': ['clim', 'clim_manual_low', 'clim_manual_high']})
|
|
240
282
|
|
|
241
283
|
maps_date = [getattr(maps, 'date_average', None) or getattr(maps, 'date', None) for maps in st.session_state.map[imager_select]]
|
|
242
284
|
if len(maps_date) > 1:
|
|
@@ -248,14 +290,26 @@ def run():
|
|
|
248
290
|
|
|
249
291
|
running_map = st.session_state.map[imager_select][maps_date.index(running_map_date)]
|
|
250
292
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
293
|
+
manual_clim = plotviewopt_container.checkbox('Provide clims values', on_change=delete_from_state, kwargs={'vars': ['clim']})
|
|
294
|
+
if manual_clim:
|
|
295
|
+
col1, col2 = plotviewopt_container.columns(2)
|
|
296
|
+
if 'clim_manual_low' not in st.session_state:
|
|
297
|
+
st.session_state.clim_manual_low = st.session_state.map_colormap_limits[imager_select][0]
|
|
298
|
+
qmin = col1.number_input('Low clim value', label_visibility='collapsed', key='clim_manual_low')
|
|
299
|
+
if 'clim_manual_high' not in st.session_state:
|
|
300
|
+
st.session_state.clim_manual_high = st.session_state.map_colormap_limits[imager_select][1]
|
|
301
|
+
qmax = col2.number_input('High clim value', label_visibility='collapsed', key='clim_manual_high')
|
|
302
|
+
st.session_state.map_colormap_limits[imager_select] = [qmin, qmax]
|
|
303
|
+
else:
|
|
304
|
+
qmin = st.session_state.map_colormap_limits[imager_select][0]
|
|
305
|
+
qmax = st.session_state.map_colormap_limits[imager_select][1]
|
|
306
|
+
cmmin, cpmax = config_sliders.slider_image_pmclims[image_mode]
|
|
307
|
+
if 'clim' not in st.session_state:
|
|
308
|
+
st.session_state.clim = [float(qmin), float(qmax)]
|
|
309
|
+
st.session_state.map_colormap_limits[imager_select] = \
|
|
310
|
+
plotviewopt_container.slider('Images colorbar limits:',
|
|
311
|
+
min_value=float(cmmin), max_value=float(cpmax),
|
|
312
|
+
key='clim')
|
|
259
313
|
|
|
260
314
|
#############################################################
|
|
261
315
|
# Finalize the geometrical model
|
|
@@ -290,35 +344,28 @@ def run():
|
|
|
290
344
|
|
|
291
345
|
#############################################################
|
|
292
346
|
# Plot main and supplement figure images
|
|
293
|
-
fig, axis =
|
|
294
|
-
if st.session_state.plot_mesh_mode == 'Skeleton':
|
|
295
|
-
model.plot(axis, mode='Skeleton')
|
|
296
|
-
elif st.session_state.plot_mesh_mode == 'Full':
|
|
297
|
-
model.plot(axis, mode='Skeleton')
|
|
298
|
-
model.plot(axis, mode='Full')
|
|
299
|
-
elif st.session_state.plot_mesh_mode == 'Surface':
|
|
300
|
-
model.plot(axis, only_surface=True)
|
|
301
|
-
|
|
302
|
-
if star_field:
|
|
303
|
-
plot_bodies(axis, bodies_list, running_map)
|
|
304
|
-
axis.legend()
|
|
347
|
+
fig, axis = figure_streamlit(st, running_map, image_mode, imager_select, model)
|
|
305
348
|
st.pyplot(fig)
|
|
306
349
|
|
|
307
|
-
if plt_supp_imagers
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
350
|
+
if plt_supp_imagers:
|
|
351
|
+
if len(st.session_state.imagers_list_) < 3:
|
|
352
|
+
other_element = [element for element in st.session_state.imagers_list_ if element != imager_select][0]
|
|
353
|
+
fig, axis = figure_streamlit(st, get_closest(st.session_state.map[other_element], running_map_date), image_mode, other_element, model)
|
|
354
|
+
st.pyplot(fig)
|
|
355
|
+
else:
|
|
356
|
+
supl_imagers_list = copy(st.session_state.imagers_list_)
|
|
357
|
+
supl_imagers_list.remove(imager_select)
|
|
358
|
+
supl_imagers = st.select_slider('Select supplement imagers',
|
|
359
|
+
options=supl_imagers_list,
|
|
360
|
+
value=(supl_imagers_list[0],
|
|
361
|
+
supl_imagers_list[-1]),
|
|
362
|
+
key='supl_imagers')
|
|
363
|
+
col1, col2 = st.columns(2)
|
|
364
|
+
fig, axis = figure_streamlit(st, get_closest(st.session_state.map[supl_imagers[0]], running_map_date), image_mode, supl_imagers[0], model)
|
|
365
|
+
col1.pyplot(fig)
|
|
366
|
+
fig, axis = figure_streamlit(st, get_closest(st.session_state.map[supl_imagers[1]], running_map_date), image_mode, supl_imagers[1], model)
|
|
367
|
+
model.plot(axis, mode='Skeleton')
|
|
368
|
+
col2.pyplot(fig)
|
|
322
369
|
|
|
323
370
|
#############################################################
|
|
324
371
|
# Store the fitting
|
|
@@ -39,7 +39,8 @@ def change_long_lat_sliders(st):
|
|
|
39
39
|
if st.session_state.coord_system == 'HGS':
|
|
40
40
|
center_ = st.session_state.center.transform_to(frames.HeliographicStonyhurst)
|
|
41
41
|
elif st.session_state.coord_system == 'HGC':
|
|
42
|
-
center_ = st.session_state.center.transform_to(frames.HeliographicCarrington
|
|
42
|
+
center_ = st.session_state.center.transform_to(frames.HeliographicCarrington(observer='Earth',
|
|
43
|
+
obstime=st.session_state.center.obstime))
|
|
43
44
|
st.session_state.longit = float(center_.lon.to_value(u.degree))
|
|
44
45
|
st.session_state.latitu = float(center_.lat.to_value(u.degree))
|
|
45
46
|
|
|
@@ -283,7 +283,8 @@ class spheroid:
|
|
|
283
283
|
"""
|
|
284
284
|
Returns the spheroid parameters as `~pandas.DataFrame`.
|
|
285
285
|
"""
|
|
286
|
-
center_ = self.center.transform_to(frames.HeliographicCarrington
|
|
286
|
+
center_ = self.center.transform_to(frames.HeliographicCarrington(observer='Earth',
|
|
287
|
+
obstime=self.center.obstime))
|
|
287
288
|
data_dict = {
|
|
288
289
|
'hgln': self.center.lon.to_value(u.degree),
|
|
289
290
|
'hglt': self.center.lat.to_value(u.degree),
|
|
@@ -303,7 +304,8 @@ class spheroid:
|
|
|
303
304
|
'''
|
|
304
305
|
Returns the Spheroid object and parameters in a printable sting array.
|
|
305
306
|
'''
|
|
306
|
-
center_ = self.center.transform_to(frames.HeliographicCarrington
|
|
307
|
+
center_ = self.center.transform_to(frames.HeliographicCarrington(observer='Earth',
|
|
308
|
+
obstime=self.center.obstime))
|
|
307
309
|
output = '<Spheroid object \n'
|
|
308
310
|
output += 'HGLN = %3.2f degrees \n'%self.center.lon.to_value(u.degree)
|
|
309
311
|
output += 'HGLT = %3.2f degrees \n'%self.center.lat.to_value(u.degree)
|
|
@@ -402,7 +404,8 @@ class ellipsoid(spheroid):
|
|
|
402
404
|
"""
|
|
403
405
|
Returns the ellipsoid parameters as `~pandas.DataFrame`.
|
|
404
406
|
"""
|
|
405
|
-
center_ = self.center.transform_to(frames.HeliographicCarrington
|
|
407
|
+
center_ = self.center.transform_to(frames.HeliographicCarrington(observer='Earth',
|
|
408
|
+
obstime=self.center.obstime))
|
|
406
409
|
data_dict = {
|
|
407
410
|
'hgln': self.center.lon.to_value(u.degree),
|
|
408
411
|
'hglt': self.center.lat.to_value(u.degree),
|
|
@@ -469,7 +472,8 @@ class ellipsoid(spheroid):
|
|
|
469
472
|
'''
|
|
470
473
|
Returns the Ellipsoid object and parameters in a printable sting array.
|
|
471
474
|
'''
|
|
472
|
-
center_ = self.center.transform_to(frames.HeliographicCarrington
|
|
475
|
+
center_ = self.center.transform_to(frames.HeliographicCarrington(observer='Earth',
|
|
476
|
+
obstime=self.center.obstime))
|
|
473
477
|
output = '<Ellipsoid object \n'
|
|
474
478
|
output += 'HGLN = %3.2f degrees \n'%self.center.lon.to_value(u.degree)
|
|
475
479
|
output += 'HGLT = %3.2f degrees \n'%self.center.lat.to_value(u.degree)
|
|
@@ -669,7 +673,8 @@ class gcs():
|
|
|
669
673
|
"""
|
|
670
674
|
Returns the GCS parameters as `~pandas.DataFrame`.
|
|
671
675
|
"""
|
|
672
|
-
center_ = self.center.transform_to(frames.HeliographicCarrington
|
|
676
|
+
center_ = self.center.transform_to(frames.HeliographicCarrington(observer='Earth',
|
|
677
|
+
obstime=self.center.obstime))
|
|
673
678
|
data_dict = {
|
|
674
679
|
'hgln': self.center.lon.to_value(u.degree),
|
|
675
680
|
'hglt': self.center.lat.to_value(u.degree),
|
|
@@ -689,7 +694,8 @@ class gcs():
|
|
|
689
694
|
'''
|
|
690
695
|
Returns the GCS object and parameters in a printable sting array.
|
|
691
696
|
'''
|
|
692
|
-
center_ = self.center.transform_to(frames.HeliographicCarrington
|
|
697
|
+
center_ = self.center.transform_to(frames.HeliographicCarrington(observer='Earth',
|
|
698
|
+
obstime=self.center.obstime))
|
|
693
699
|
output = '<GCS object \n'
|
|
694
700
|
output += 'HGLN = %3.2f degrees \n'%self.center.lon.to_value(u.degree)
|
|
695
701
|
output += 'HGLT = %3.2f degrees \n'%self.center.lat.to_value(u.degree)
|
|
@@ -19,16 +19,14 @@
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
import datetime
|
|
22
|
-
import json
|
|
23
22
|
|
|
24
23
|
import astropy.units as u
|
|
25
|
-
import numpy as np
|
|
26
|
-
import pandas as pd
|
|
27
24
|
|
|
28
25
|
from PyThea.callbacks import change_fitting_sliders, change_long_lat_sliders
|
|
29
26
|
from PyThea.config.config_sliders import sliders_dict as sd
|
|
30
27
|
from PyThea.geometrical_models import ellipsoid, gcs, spheroid
|
|
31
|
-
from PyThea.utils import get_hek_flare, model_fittings
|
|
28
|
+
from PyThea.utils import (get_hek_flare, make_figure, model_fittings,
|
|
29
|
+
plot_bodies, plot_solar_reference_lines)
|
|
32
30
|
|
|
33
31
|
|
|
34
32
|
def date_and_event_selection(st):
|
|
@@ -68,29 +66,14 @@ def date_and_event_selection(st):
|
|
|
68
66
|
if uploaded_file.type != 'application/json':
|
|
69
67
|
st.sidebar.error('Unsupported file type')
|
|
70
68
|
st.stop()
|
|
71
|
-
|
|
72
|
-
st.session_state.
|
|
73
|
-
|
|
74
|
-
st.session_state.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if 'kinematics' in fitting:
|
|
80
|
-
kinematics = fitting['kinematics']
|
|
81
|
-
else:
|
|
82
|
-
# TODO: Remove this in version 1.0.0
|
|
83
|
-
st.warning('**Warning:** The .json fitting file does not contain the "kinematics" information. \
|
|
84
|
-
This means that the file was prodused using Pythea with <V0.6.0. \
|
|
85
|
-
**To resolve this:** Just do a save of the loaded fitting now and replace \
|
|
86
|
-
the old file with the new one. This will not alter your fittings.')
|
|
87
|
-
kinematics = {'fit_method': {'type': 'polynomial', 'order': 1}}
|
|
88
|
-
|
|
89
|
-
st.session_state.model_fittings = model_fittings(fitting['event_selected'],
|
|
90
|
-
fitting['date_process'],
|
|
91
|
-
fitting['geometrical_model']['type'],
|
|
92
|
-
parameters,
|
|
93
|
-
kinematics=kinematics)
|
|
69
|
+
|
|
70
|
+
st.session_state.model_fittings = model_fittings.load_from_json(uploaded_file)
|
|
71
|
+
|
|
72
|
+
st.session_state.event_selected = st.session_state.model_fittings.event_selected
|
|
73
|
+
st.session_state.date_process = \
|
|
74
|
+
datetime.datetime.strptime(st.session_state.model_fittings.date_process, '%Y-%m-%dT%H:%M:%S.%f')
|
|
75
|
+
st.session_state.geometrical_model = st.session_state.model_fittings.geometrical_model
|
|
76
|
+
|
|
94
77
|
st.rerun()
|
|
95
78
|
|
|
96
79
|
|
|
@@ -201,13 +184,27 @@ def final_parameters_gmodel(st):
|
|
|
201
184
|
return rcenter, height, alpha, kappa, tilt
|
|
202
185
|
|
|
203
186
|
|
|
204
|
-
def
|
|
205
|
-
if 'map_clim' not in st.session_state:
|
|
206
|
-
st.session_state['map_clim'] = {}
|
|
187
|
+
def figure_streamlit(st, running_map, image_mode, imager, model):
|
|
207
188
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
189
|
+
fig, axis = make_figure(running_map, image_mode,
|
|
190
|
+
clim=st.session_state.map_colormap_limits[imager],
|
|
191
|
+
clip_model=st.session_state.clip_model,
|
|
192
|
+
median_filter=st.session_state.images_median_filter)
|
|
193
|
+
|
|
194
|
+
if st.session_state.plot_mesh_mode == 'Skeleton':
|
|
195
|
+
model.plot(axis, mode='Skeleton')
|
|
196
|
+
elif st.session_state.plot_mesh_mode == 'Full':
|
|
197
|
+
model.plot(axis, mode='Skeleton')
|
|
198
|
+
model.plot(axis, mode='Full')
|
|
199
|
+
elif st.session_state.plot_mesh_mode == 'Surface':
|
|
200
|
+
model.plot(axis, only_surface=True)
|
|
201
|
+
|
|
202
|
+
if st.session_state.star_field:
|
|
203
|
+
plot_bodies(axis, st.session_state.bodies_list, running_map)
|
|
204
|
+
axis.legend()
|
|
205
|
+
|
|
206
|
+
if st.session_state.plot_solar_reference_lines_:
|
|
207
|
+
plot_solar_reference_lines(axis, st.session_state.plot_solar_reference_lines_bodies_list,
|
|
208
|
+
running_map, mode=st.session_state.plot_solar_reference_lines_mode)
|
|
209
|
+
|
|
210
|
+
return fig, axis
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from astropy.time import TimeDelta
|
|
2
|
+
from aiapy.calibrate import fix_observer_location, update_pointing
|
|
3
|
+
|
|
4
|
+
__all__ = ['prep_aia']
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def prep_aia(map_sequence):
|
|
8
|
+
map_sequence = [update_pointing(tmap) for tmap in map_sequence]
|
|
9
|
+
map_sequence = [fix_observer_location(tmap) for tmap in map_sequence]
|
|
10
|
+
|
|
11
|
+
for map_ in map_sequence:
|
|
12
|
+
map_.meta['DATE-AVG'] = (map_.date + TimeDelta(map_.meta['exptime']/2, format='sec')).value
|
|
13
|
+
|
|
14
|
+
return map_sequence
|
|
@@ -8,8 +8,8 @@ import warnings
|
|
|
8
8
|
import astropy.units as u
|
|
9
9
|
import numpy as np
|
|
10
10
|
import sunpy.map
|
|
11
|
-
from aiapy.calibrate import fix_observer_location, update_pointing
|
|
12
11
|
|
|
12
|
+
import PyThea.sunpy_dev.extern.sunkit_instruments.aia.utils # noqa
|
|
13
13
|
import PyThea.sunpy_dev.extern.sunkit_instruments.lasco.utils # noqa
|
|
14
14
|
import PyThea.sunpy_dev.extern.sunkit_instruments.stereo.utils # noqa
|
|
15
15
|
|
|
@@ -17,17 +17,17 @@ __all__ = ['maps_sequence_processing', 'get_closest', 'normalize_exposure',
|
|
|
17
17
|
'prepare_maps', 'difference_maps', 'mask_occulter']
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def maps_sequence_processing(map_sequence,
|
|
20
|
+
def maps_sequence_processing(map_sequence, **kwargs):
|
|
21
21
|
"""
|
|
22
|
-
Returns a sequence of maps which is processed as running
|
|
22
|
+
Returns a sequence of maps which is processed as plain images, running or base difference images.
|
|
23
23
|
|
|
24
24
|
Parameters
|
|
25
25
|
----------
|
|
26
26
|
map_sequence : `~sunpy.map.GenericMap`
|
|
27
27
|
A list SunPy maps.
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
The type of sequence processing
|
|
29
|
+
image_mode : '~str'
|
|
30
|
+
The type of sequence processing: 'Running Diff.', 'Base Diff.', 'Plain'
|
|
31
31
|
|
|
32
32
|
Returns
|
|
33
33
|
-------
|
|
@@ -35,18 +35,24 @@ def maps_sequence_processing(map_sequence, seq_type='Plain'):
|
|
|
35
35
|
A SunPy map.
|
|
36
36
|
"""
|
|
37
37
|
|
|
38
|
+
if len(map_sequence) == 0:
|
|
39
|
+
return []
|
|
40
|
+
|
|
41
|
+
seq_type = kwargs.get('image_mode', 'Plain')
|
|
42
|
+
diff_num = kwargs.get('diff_num', 1 if seq_type == 'Running Diff.' else 0 if seq_type == 'Base Diff.' else None)
|
|
43
|
+
|
|
38
44
|
normalized = True if True in [tmap.exposure_time == 1.0*u.second for tmap in map_sequence] else False
|
|
39
45
|
if not normalized:
|
|
40
46
|
warnings.warn('Warning [maps_sequence_processing]: The exposure time of the maps is not normalized.')
|
|
41
47
|
|
|
42
48
|
smap = []
|
|
43
49
|
if seq_type == 'Running Diff.':
|
|
44
|
-
for i in range(1, len(map_sequence)):
|
|
45
|
-
smap_diff = difference_maps(map_sequence[i], map_sequence[i-
|
|
50
|
+
for i in range(1+diff_num, len(map_sequence)):
|
|
51
|
+
smap_diff = difference_maps(map_sequence[i], map_sequence[i-diff_num])
|
|
46
52
|
smap.append(smap_diff)
|
|
47
53
|
if seq_type == 'Base Diff.':
|
|
48
54
|
for i in range(1, len(map_sequence)):
|
|
49
|
-
smap_diff = difference_maps(map_sequence[i], map_sequence[
|
|
55
|
+
smap_diff = difference_maps(map_sequence[i], map_sequence[diff_num])
|
|
50
56
|
smap.append(smap_diff)
|
|
51
57
|
if seq_type == 'Plain':
|
|
52
58
|
for i in range(0, len(map_sequence)):
|
|
@@ -132,6 +138,9 @@ def filter_maps(map_sequence, **kwargs):
|
|
|
132
138
|
|
|
133
139
|
'''
|
|
134
140
|
|
|
141
|
+
if len(map_sequence) == 0:
|
|
142
|
+
return []
|
|
143
|
+
|
|
135
144
|
if 'exposure' in kwargs.keys():
|
|
136
145
|
map_sequence = [tmap for tmap in map_sequence if tmap.exposure_time > kwargs['exposure']*u.second]
|
|
137
146
|
|
|
@@ -145,6 +154,7 @@ def filter_maps(map_sequence, **kwargs):
|
|
|
145
154
|
sequence_final = sunpy.map.Map(map_sequence, sequence=True)
|
|
146
155
|
else:
|
|
147
156
|
sequence_final = []
|
|
157
|
+
|
|
148
158
|
return sequence_final
|
|
149
159
|
|
|
150
160
|
|
|
@@ -169,16 +179,16 @@ def prepare_maps(map_sequence, **kwargs):
|
|
|
169
179
|
A SunPy map.
|
|
170
180
|
|
|
171
181
|
'''
|
|
172
|
-
detector = map_sequence[0].detector
|
|
173
|
-
print(f'Preparing image sequence for {detector}.')
|
|
174
182
|
|
|
175
183
|
if len(map_sequence) == 0:
|
|
176
184
|
return []
|
|
177
185
|
|
|
186
|
+
detector = map_sequence[0].detector
|
|
187
|
+
print(f'Preparing image sequence for {detector}. This could take a while...')
|
|
188
|
+
|
|
178
189
|
# Prepare the maps before anything else
|
|
179
190
|
if detector == 'AIA':
|
|
180
|
-
map_sequence =
|
|
181
|
-
map_sequence = [fix_observer_location(tmap) for tmap in map_sequence]
|
|
191
|
+
map_sequence = PyThea.sunpy_dev.extern.sunkit_instruments.aia.utils.prep_aia(map_sequence)
|
|
182
192
|
elif detector == 'COR1':
|
|
183
193
|
if 'polar' not in kwargs.keys():
|
|
184
194
|
map_sequence = PyThea.sunpy_dev.extern.sunkit_instruments.stereo.utils.cor_polariz(map_sequence)
|
|
@@ -279,3 +289,7 @@ def mask_occulter(smap, apply_mask=True, mask_value=0):
|
|
|
279
289
|
smap.data[mask_inner+mask_outer] = mask_value
|
|
280
290
|
return sunpy.map.Map(smap.data, smap.meta)
|
|
281
291
|
return mask_inner+mask_outer
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def maps_clims(images):
|
|
295
|
+
return [np.nanquantile(images[1].data, 0.20)-10, np.nanquantile(images[1].data, 0.80)+10]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A place for the more generic tests that do not fit in the other categories
|
|
3
|
+
|
|
4
|
+
Note
|
|
5
|
+
----
|
|
6
|
+
Before you start the test the PyThea pkg should be in the python path
|
|
7
|
+
export PYTHONPATH="${PYTHONPATH}:{top_level_dir_that_pythea_lives}/PyThea"
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_database_dir_exists():
|
|
15
|
+
"""
|
|
16
|
+
Tests that Pythea's database directory exists.
|
|
17
|
+
"""
|
|
18
|
+
# Skip the test if running in GitHub Actions
|
|
19
|
+
if os.environ.get('CI') == 'true':
|
|
20
|
+
print("Skipping test as it's running in GitHub Actions.")
|
|
21
|
+
return
|
|
22
|
+
|
|
23
|
+
database_dir = os.path.join(Path.home(), 'PyThea')
|
|
24
|
+
assert os.path.exists(database_dir), f"PyThea's database directory '{database_dir}' does not exist."
|
|
File without changes
|
|
@@ -23,6 +23,7 @@ import io
|
|
|
23
23
|
import json
|
|
24
24
|
import os
|
|
25
25
|
import re
|
|
26
|
+
import warnings
|
|
26
27
|
from copy import copy
|
|
27
28
|
from pathlib import Path
|
|
28
29
|
|
|
@@ -35,13 +36,17 @@ import numpy as np
|
|
|
35
36
|
import pandas as pd
|
|
36
37
|
import seaborn as sns
|
|
37
38
|
import sunpy.map
|
|
39
|
+
from astropy.coordinates import SkyCoord
|
|
40
|
+
from astropy.visualization.wcsaxes.wcsapi import wcsapi_to_celestial_frame
|
|
38
41
|
from scipy.interpolate import UnivariateSpline
|
|
42
|
+
from scipy.ndimage import median_filter
|
|
39
43
|
from scipy.optimize import curve_fit
|
|
40
|
-
from sunpy.coordinates import get_horizons_coord
|
|
44
|
+
from sunpy.coordinates import frames, get_horizons_coord
|
|
41
45
|
from sunpy.map.maputils import contains_coordinate
|
|
42
46
|
from sunpy.net import Fido
|
|
43
47
|
from sunpy.net import attrs as a
|
|
44
48
|
from sunpy.time import parse_time
|
|
49
|
+
from sunpy.visualization import drawing
|
|
45
50
|
|
|
46
51
|
from PyThea.config.selected_bodies import bodies_dict
|
|
47
52
|
from PyThea.config.selected_imagers import imager_dict
|
|
@@ -86,13 +91,15 @@ def make_figure(map, image_mode, clim=[-20, 20], clip_model=True, **kwargs):
|
|
|
86
91
|
|
|
87
92
|
if image_mode == 'Plain':
|
|
88
93
|
# TODO: For plain images or when EUVIA-B are used, this does not work very well.
|
|
89
|
-
map.plot()
|
|
94
|
+
map.plot(norm=colors.Normalize(vmin=clim[0], vmax=clim[1]))
|
|
90
95
|
else:
|
|
96
|
+
median_filter_value = kwargs.get('median_filter', 1)
|
|
97
|
+
if median_filter_value != 1:
|
|
98
|
+
map = sunpy.map.Map(median_filter(map.data, size=int(median_filter_value)), map.meta)
|
|
91
99
|
map.plot(cmap='Greys_r',
|
|
92
100
|
norm=colors.Normalize(vmin=clim[0], vmax=clim[1]))
|
|
93
101
|
|
|
94
102
|
map.draw_limb(resolution=90)
|
|
95
|
-
# map.draw_grid(linewidth=2, color='red') # TODO: This takes too much computation time. Maybe for AIA or EUVI?
|
|
96
103
|
|
|
97
104
|
yax = axis.coords[1]
|
|
98
105
|
yax.set_ticklabel(rotation=90)
|
|
@@ -127,6 +134,42 @@ def plot_bodies(axis, bodies_list, smap):
|
|
|
127
134
|
fillstyle='none', markersize=6, label=body)
|
|
128
135
|
|
|
129
136
|
|
|
137
|
+
def plot_solar_reference_lines(axis, bodies_list, smap, mode='Limb from Obs.'):
|
|
138
|
+
'''
|
|
139
|
+
Plots solar reference lines (e.g. solar limb, central meridians, equator) in wcs axis.
|
|
140
|
+
'''
|
|
141
|
+
def draw_central_meridian(axis, body_coo, date, color):
|
|
142
|
+
body_coo = body_coo.transform_to(frames.HeliographicStonyhurst)
|
|
143
|
+
constant_lon = SkyCoord(body_coo.lon, np.linspace(-90, 90, 90) * u.deg,
|
|
144
|
+
frame=frames.HeliographicStonyhurst(obstime=date))
|
|
145
|
+
v, _ = drawing._plot_vertices(constant_lon, axis, wcsapi_to_celestial_frame(axis.wcs), None,
|
|
146
|
+
color=color, close_path=False, linewidth=1)
|
|
147
|
+
|
|
148
|
+
for body in bodies_list:
|
|
149
|
+
try:
|
|
150
|
+
body_coo = get_horizons_coord(bodies_dict[body][0], smap.date_average)
|
|
151
|
+
except ValueError as ve:
|
|
152
|
+
print(f'Error processing {body}: {ve}')
|
|
153
|
+
continue
|
|
154
|
+
|
|
155
|
+
if mode in ['Limb from Obs.', 'limb']:
|
|
156
|
+
drawing.limb(axis, body_coo, color=bodies_dict[body][1],
|
|
157
|
+
linewidth=1, resolution=90, label=f'Limb seen from {body}')
|
|
158
|
+
if mode in ['Central Meridian from Obs.', 'meridian']:
|
|
159
|
+
draw_central_meridian(axis, body_coo, smap.date_average, bodies_dict[body][1])
|
|
160
|
+
|
|
161
|
+
if mode in ['Carr. Prime Meridian+Solar Equator', ['carr-me']]:
|
|
162
|
+
drawing.equator(axis, linewidth=1, resolution=90)
|
|
163
|
+
drawing.prime_meridian(axis, linewidth=1, resolution=90)
|
|
164
|
+
elif mode in ['Stonyhurst Grid', ['stony-grid']]:
|
|
165
|
+
earth = get_horizons_coord(3, smap.date_average)
|
|
166
|
+
draw_central_meridian(axis, earth, smap.date_average, 'white')
|
|
167
|
+
smap.draw_grid(linewidth=1, color='red', system='stonyhurst', alpha=0.8)
|
|
168
|
+
elif mode in ['Carrington Grid', ['carr-grid']]:
|
|
169
|
+
drawing.prime_meridian(axis, linewidth=1, resolution=90)
|
|
170
|
+
smap.draw_grid(linewidth=1, color='red', system='carrington', alpha=0.8)
|
|
171
|
+
|
|
172
|
+
|
|
130
173
|
def download_fits(date_process, imager, time_range=[-1, 1]):
|
|
131
174
|
'''
|
|
132
175
|
Downloads the imaging data (fits files) from VSO
|
|
@@ -134,24 +177,26 @@ def download_fits(date_process, imager, time_range=[-1, 1]):
|
|
|
134
177
|
timerange = a.Time(date_process + datetime.timedelta(hours=time_range[0]),
|
|
135
178
|
date_process + datetime.timedelta(hours=time_range[1]))
|
|
136
179
|
|
|
137
|
-
|
|
180
|
+
maps_ = []
|
|
138
181
|
args = imager_dict[imager][0]
|
|
139
182
|
result = Fido.search(timerange, *args)
|
|
140
183
|
print(result)
|
|
141
184
|
if result:
|
|
142
185
|
downloaded_files = Fido.fetch(result, path=f'{database_dir}'+'/data/{source}/{instrument}/'+'/{file}')
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
186
|
+
for file_path in downloaded_files:
|
|
187
|
+
try:
|
|
188
|
+
map_ = sunpy.map.Map(file_path)
|
|
189
|
+
maps_.append(map_)
|
|
190
|
+
except RuntimeError as err:
|
|
191
|
+
print('Handling RuntimeError error:', err)
|
|
192
|
+
except OSError as err:
|
|
193
|
+
print('Handling OSError error:', err)
|
|
194
|
+
os.remove(file_path)
|
|
195
|
+
print(f"File '{file_path}' has been removed.")
|
|
196
|
+
if maps_:
|
|
197
|
+
maps_ = sunpy.map.Map(maps_, sequence=True)
|
|
198
|
+
|
|
199
|
+
return maps_
|
|
155
200
|
|
|
156
201
|
|
|
157
202
|
def maps_process(maps_dict_in, imagers_list_in, image_mode, **kwargs):
|
|
@@ -183,15 +228,21 @@ def maps_process(maps_dict_in, imagers_list_in, image_mode, **kwargs):
|
|
|
183
228
|
return maps_dict_out, imagers_list_out
|
|
184
229
|
|
|
185
230
|
|
|
186
|
-
def single_imager_maps_process(
|
|
231
|
+
def single_imager_maps_process(map_list, skip=None, **kwargs):
|
|
187
232
|
'''
|
|
188
233
|
Process the images for a single imager and return the final maps.
|
|
189
234
|
'''
|
|
190
|
-
map_list_out = filter_maps(map_list_in, **kwargs)
|
|
191
|
-
map_list_out = prepare_maps(map_list_out, **kwargs)
|
|
192
|
-
map_list_out = maps_sequence_processing(map_list_out, seq_type=image_mode)
|
|
193
235
|
|
|
194
|
-
|
|
236
|
+
if 'filter' not in str(skip or ''):
|
|
237
|
+
map_list = filter_maps(map_list, **kwargs)
|
|
238
|
+
|
|
239
|
+
if 'prepare' not in str(skip or ''):
|
|
240
|
+
map_list = prepare_maps(map_list, **kwargs)
|
|
241
|
+
|
|
242
|
+
if 'sequence_processing' not in str(skip or ''):
|
|
243
|
+
map_list = maps_sequence_processing(map_list, **kwargs)
|
|
244
|
+
|
|
245
|
+
return map_list
|
|
195
246
|
|
|
196
247
|
|
|
197
248
|
# TODO: Implement units here
|
|
@@ -207,6 +258,36 @@ class model_fittings:
|
|
|
207
258
|
self.parameters = model_parameters
|
|
208
259
|
self.kinematics = kinematics
|
|
209
260
|
|
|
261
|
+
@staticmethod
|
|
262
|
+
def load_from_json(json_file):
|
|
263
|
+
if isinstance(json_file, str):
|
|
264
|
+
with open(json_file, 'r') as file:
|
|
265
|
+
json_content = file.read()
|
|
266
|
+
fitting = json.loads(json_content)
|
|
267
|
+
else:
|
|
268
|
+
fitting = json.loads(json_file.read())
|
|
269
|
+
|
|
270
|
+
table_indx = [datetime.datetime.strptime(t, '%Y-%m-%dT%H:%M:%S.%f') for t in fitting['geometrical_model']['parameters']['time']]
|
|
271
|
+
parameters = pd.DataFrame(fitting['geometrical_model']['parameters'], index=table_indx)
|
|
272
|
+
parameters = parameters.drop(['time'], axis=1)
|
|
273
|
+
if 'kinematics' in fitting:
|
|
274
|
+
kinematics = fitting['kinematics']
|
|
275
|
+
else:
|
|
276
|
+
# TODO: Remove this in version 1.0.0
|
|
277
|
+
warnings.warn('The .json fitting file does not contain the "kinematics" information. \n \
|
|
278
|
+
This means that the file was prodused using Pythea with <V0.6.0. \n \
|
|
279
|
+
To resolve this: Just do a save of the loaded fitting now and replace \n \
|
|
280
|
+
the old file with the new one. This will not alter your fittings.')
|
|
281
|
+
kinematics = {'fit_method': {'type': 'polynomial', 'order': 1}}
|
|
282
|
+
|
|
283
|
+
model_fittings_class = model_fittings(fitting['event_selected'],
|
|
284
|
+
fitting['date_process'],
|
|
285
|
+
fitting['geometrical_model']['type'],
|
|
286
|
+
parameters,
|
|
287
|
+
kinematics=kinematics)
|
|
288
|
+
|
|
289
|
+
return model_fittings_class
|
|
290
|
+
|
|
210
291
|
def model_id(self):
|
|
211
292
|
str_id = self.event_selected.replace('-', '').replace(':', '').replace('|', 'D').replace('.', 'p') + 'M' + self.geometrical_model
|
|
212
293
|
return str_id
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyThea
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.0
|
|
4
4
|
Summary: PyThea: A software package to reconstruct the 3D structure of CMEs and shock waves
|
|
5
5
|
Home-page: https://github.com/AthKouloumvakos/PyThea
|
|
6
6
|
Author: Athanasios Kouloumvakos
|
|
@@ -27,8 +27,8 @@ Requires-Dist: aiapy
|
|
|
27
27
|
Requires-Dist: astropy
|
|
28
28
|
Requires-Dist: astroquery
|
|
29
29
|
Requires-Dist: numexpr
|
|
30
|
-
Requires-Dist: sunpy==
|
|
31
|
-
Requires-Dist: parfive==1.
|
|
30
|
+
Requires-Dist: sunpy==5.1.2
|
|
31
|
+
Requires-Dist: parfive==2.1.0
|
|
32
32
|
Requires-Dist: pooch
|
|
33
33
|
Requires-Dist: matplotlib
|
|
34
34
|
Requires-Dist: seaborn
|
|
@@ -38,6 +38,8 @@ PyThea/extensions/buttons.py
|
|
|
38
38
|
PyThea/sunpy_dev/__init__.py
|
|
39
39
|
PyThea/sunpy_dev/extern/__init__.py
|
|
40
40
|
PyThea/sunpy_dev/extern/sunkit_instruments/__init__.py
|
|
41
|
+
PyThea/sunpy_dev/extern/sunkit_instruments/aia/__init__.py
|
|
42
|
+
PyThea/sunpy_dev/extern/sunkit_instruments/aia/utils.py
|
|
41
43
|
PyThea/sunpy_dev/extern/sunkit_instruments/lasco/__init__.py
|
|
42
44
|
PyThea/sunpy_dev/extern/sunkit_instruments/lasco/utils.py
|
|
43
45
|
PyThea/sunpy_dev/extern/sunkit_instruments/stereo/__init__.py
|
|
@@ -14,8 +14,8 @@ dependencies:
|
|
|
14
14
|
- astropy
|
|
15
15
|
- astroquery
|
|
16
16
|
- numexpr
|
|
17
|
-
- sunpy=
|
|
18
|
-
- parfive==
|
|
17
|
+
- sunpy=5.1.2
|
|
18
|
+
- parfive==2.1.0 # The issue with streamlit and asyncio is resolved (see #13). Keep this for a while to make sure everything works smoothly.
|
|
19
19
|
- streamlit
|
|
20
20
|
- seaborn
|
|
21
21
|
- pyvista
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|