PyThea 0.11.0__tar.gz → 0.12.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.
Files changed (60) hide show
  1. pythea-0.12.0/.readthedocs.yaml +29 -0
  2. {pythea-0.11.0 → pythea-0.12.0}/CHANGELOG.md +26 -1
  3. {pythea-0.11.0/PyThea.egg-info → pythea-0.12.0}/PKG-INFO +4 -5
  4. {pythea-0.11.0 → pythea-0.12.0}/PyThea/PyThea_app.py +41 -19
  5. {pythea-0.11.0 → pythea-0.12.0}/PyThea/_version.py +2 -2
  6. {pythea-0.11.0 → pythea-0.12.0}/PyThea/config/app_styles.py +0 -5
  7. pythea-0.12.0/PyThea/config/selected_imagers.py +65 -0
  8. {pythea-0.11.0 → pythea-0.12.0}/PyThea/data/sample_data.py +1 -1
  9. {pythea-0.11.0 → pythea-0.12.0}/PyThea/sunpy_dev/map/maputils.py +7 -2
  10. {pythea-0.11.0 → pythea-0.12.0}/PyThea/test/figure_hashes.json +2 -1
  11. {pythea-0.11.0 → pythea-0.12.0}/PyThea/test/test_figures.py +28 -1
  12. {pythea-0.11.0 → pythea-0.12.0}/PyThea/test/test_remote_clients.py +2 -2
  13. {pythea-0.11.0 → pythea-0.12.0}/PyThea/utils.py +95 -29
  14. {pythea-0.11.0 → pythea-0.12.0/PyThea.egg-info}/PKG-INFO +4 -5
  15. {pythea-0.11.0 → pythea-0.12.0}/PyThea.egg-info/SOURCES.txt +1 -0
  16. {pythea-0.11.0 → pythea-0.12.0}/PyThea.egg-info/requires.txt +0 -1
  17. {pythea-0.11.0 → pythea-0.12.0}/README.md +3 -3
  18. {pythea-0.11.0 → pythea-0.12.0}/README_pypi.md +3 -3
  19. {pythea-0.11.0 → pythea-0.12.0}/environment.yml +0 -1
  20. {pythea-0.11.0 → pythea-0.12.0}/requirements.txt +0 -1
  21. {pythea-0.11.0 → pythea-0.12.0}/setup.cfg +4 -0
  22. pythea-0.11.0/PyThea/config/selected_imagers.py +0 -34
  23. {pythea-0.11.0 → pythea-0.12.0}/LICENSE.md +0 -0
  24. {pythea-0.11.0 → pythea-0.12.0}/MANIFEST.in +0 -0
  25. {pythea-0.11.0 → pythea-0.12.0}/PyThea/__init__.py +0 -0
  26. {pythea-0.11.0 → pythea-0.12.0}/PyThea/callbacks.py +0 -0
  27. {pythea-0.11.0 → pythea-0.12.0}/PyThea/config/__init__.py +0 -0
  28. {pythea-0.11.0 → pythea-0.12.0}/PyThea/config/config_sliders.py +0 -0
  29. {pythea-0.11.0 → pythea-0.12.0}/PyThea/config/selected_bodies.py +0 -0
  30. {pythea-0.11.0 → pythea-0.12.0}/PyThea/data/__init__.py +0 -0
  31. {pythea-0.11.0 → pythea-0.12.0}/PyThea/extensions/LICENSE_gcs_python.md +0 -0
  32. {pythea-0.11.0 → pythea-0.12.0}/PyThea/extensions/__init__.py +0 -0
  33. {pythea-0.11.0 → pythea-0.12.0}/PyThea/extensions/buttons.py +0 -0
  34. {pythea-0.11.0 → pythea-0.12.0}/PyThea/geometrical_models.py +0 -0
  35. {pythea-0.11.0 → pythea-0.12.0}/PyThea/modules.py +0 -0
  36. {pythea-0.11.0 → pythea-0.12.0}/PyThea/pythea_cli.py +0 -0
  37. {pythea-0.11.0 → pythea-0.12.0}/PyThea/sunpy_dev/__init__.py +0 -0
  38. {pythea-0.11.0 → pythea-0.12.0}/PyThea/sunpy_dev/extern/__init__.py +0 -0
  39. {pythea-0.11.0 → pythea-0.12.0}/PyThea/sunpy_dev/extern/sunkit_instruments/__init__.py +0 -0
  40. {pythea-0.11.0 → pythea-0.12.0}/PyThea/sunpy_dev/extern/sunkit_instruments/aia/__init__.py +0 -0
  41. {pythea-0.11.0 → pythea-0.12.0}/PyThea/sunpy_dev/extern/sunkit_instruments/aia/utils.py +0 -0
  42. {pythea-0.11.0 → pythea-0.12.0}/PyThea/sunpy_dev/extern/sunkit_instruments/lasco/__init__.py +0 -0
  43. {pythea-0.11.0 → pythea-0.12.0}/PyThea/sunpy_dev/extern/sunkit_instruments/lasco/utils.py +0 -0
  44. {pythea-0.11.0 → pythea-0.12.0}/PyThea/sunpy_dev/extern/sunkit_instruments/stereo/__init__.py +0 -0
  45. {pythea-0.11.0 → pythea-0.12.0}/PyThea/sunpy_dev/extern/sunkit_instruments/stereo/utils.py +0 -0
  46. {pythea-0.11.0 → pythea-0.12.0}/PyThea/sunpy_dev/map/__init__.py +0 -0
  47. {pythea-0.11.0 → pythea-0.12.0}/PyThea/test/Pythea_test.py +0 -0
  48. {pythea-0.11.0 → pythea-0.12.0}/PyThea/test/__init__.py +0 -0
  49. {pythea-0.11.0 → pythea-0.12.0}/PyThea/test/conftest.py +0 -0
  50. {pythea-0.11.0 → pythea-0.12.0}/PyThea/test/test_geometrical_models.py +0 -0
  51. {pythea-0.11.0 → pythea-0.12.0}/PyThea/test/test_imports.py +0 -0
  52. {pythea-0.11.0 → pythea-0.12.0}/PyThea/test/test_utils.py +0 -0
  53. {pythea-0.11.0 → pythea-0.12.0}/PyThea/version.py +0 -0
  54. {pythea-0.11.0 → pythea-0.12.0}/PyThea.egg-info/.DS_Store +0 -0
  55. {pythea-0.11.0 → pythea-0.12.0}/PyThea.egg-info/dependency_links.txt +0 -0
  56. {pythea-0.11.0 → pythea-0.12.0}/PyThea.egg-info/entry_points.txt +0 -0
  57. {pythea-0.11.0 → pythea-0.12.0}/PyThea.egg-info/not-zip-safe +0 -0
  58. {pythea-0.11.0 → pythea-0.12.0}/PyThea.egg-info/top_level.txt +0 -0
  59. {pythea-0.11.0 → pythea-0.12.0}/pyproject.toml +0 -0
  60. {pythea-0.11.0 → pythea-0.12.0}/setup.py +0 -0
@@ -0,0 +1,29 @@
1
+ # .readthedocs.yaml
2
+ # Read the Docs configuration file
3
+ # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
4
+
5
+ # Required
6
+ version: 2
7
+
8
+ # Set the version of Python and other tools you might need
9
+ build:
10
+ os: ubuntu-22.04
11
+ tools:
12
+ python: "3.9"
13
+ # You can also specify other tool versions:
14
+ # nodejs: "16"
15
+ # rust: "1.55"
16
+ # golang: "1.17"
17
+
18
+ # Build documentation in the docs/ directory with Sphinx
19
+ sphinx:
20
+ configuration: docs/source/conf.py
21
+
22
+ # If using Sphinx, optionally build your docs in additional formats such as PDF
23
+ # formats:
24
+ # - pdf
25
+
26
+ # Optionally declare the Python requirements required to build your docs
27
+ python:
28
+ install:
29
+ - requirements: docs/source/requirements.txt
@@ -1,4 +1,29 @@
1
- # v0.11.0 (17-April-2024)
1
+ # v0.12.0 (09-Jun-2024)
2
+
3
+ ## Features
4
+ - Adds more imaging data from SDO/AIA.
5
+ - Adds acceleration calculation in the kinematic plots.
6
+ - Implements acceleration plotting in the app.
7
+ - Includes fits file name in fitting files and dataframes.
8
+ - Highlights a row in the fitting table when fitting exist in table.
9
+
10
+ ## Major Changes
11
+ - Decouples the loading of fits files from download_fits function.
12
+
13
+ ## Minor Changes
14
+ - Improves configuration dictionary for selected imagers.
15
+ - Improves json warning message in the main app page.
16
+ - Adds documentation page link to the main app page.
17
+ - Updates README files.
18
+ - Improves plot_fitting_model and adds figure test.
19
+ - Improves application layout.
20
+
21
+ ## Bug Fixes
22
+ - Fixes a potential bug in filter_maps when no filtering is applied.
23
+ - Fixes a bug with progress bar with stqdm.
24
+ - Fixes a bug with image processing mode selection.
25
+
26
+ # v0.11.0 (19-May-2024)
2
27
 
3
28
  ## Features
4
29
  - Adds tests for ellipsoid location on AIA and STEREO COR images.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyThea
3
- Version: 0.11.0
3
+ Version: 0.12.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
@@ -35,7 +35,6 @@ Requires-Dist: matplotlib
35
35
  Requires-Dist: seaborn
36
36
  Requires-Dist: streamlit
37
37
  Requires-Dist: Pillow
38
- Requires-Dist: stqdm
39
38
  Requires-Dist: lxml
40
39
  Requires-Dist: zeep
41
40
  Requires-Dist: drms
@@ -63,8 +62,8 @@ We recommend, creating a virtual environment for _PyThea_ and installing the pac
63
62
  If you use Anaconda or Miniconda (which we also recommend) you can create a virtual environment using ```conda``` and then install _PyThea_ using from PyPI using ```pip```. In the terminal do the following:
64
63
 
65
64
  ```python
66
- # Create a virtual environment. Use python=3.8 or 3.9
67
- conda create --name PyThea python=3.9
65
+ # Create a virtual environment. Use python>3.9
66
+ conda create --name PyThea python=3.10
68
67
 
69
68
  # Activate the environment
70
69
  conda activate PyThea
@@ -138,7 +137,7 @@ If there is an error when running ```PyThea streamlit``` then you can manually r
138
137
 
139
138
  ## 📙 Usage
140
139
 
141
- Complete documentation of the _PyThea_ is under construction.
140
+ Complete documentation of the _PyThea_ can be found in [https://www.pythea.org/](https://www.pythea.org/).
142
141
 
143
142
  ## 📦 Useful Python packages
144
143
 
@@ -23,7 +23,6 @@ from copy import copy
23
23
 
24
24
  import astropy.units as u
25
25
  import numpy as np
26
- import stqdm # See also https://github.com/tqdm/tqdm
27
26
  import streamlit as st
28
27
  from astropy.coordinates import Distance, SkyCoord, SphericalRepresentation
29
28
  from sunpy.coordinates import frames
@@ -38,8 +37,8 @@ from PyThea.modules import (date_and_event_selection, figure_streamlit,
38
37
  fitting_and_slider_options_container,
39
38
  fitting_sliders)
40
39
  from PyThea.sunpy_dev.map.maputils import get_closest, maps_clims
41
- from PyThea.utils import (download_fits, model_fittings, plot_fitting_model,
42
- single_imager_maps_process)
40
+ from PyThea.utils import (download_fits, load_fits, model_fittings,
41
+ plot_fitting_model, single_imager_maps_process)
43
42
  from PyThea.version import version
44
43
 
45
44
 
@@ -49,6 +48,13 @@ def delete_from_state(vars):
49
48
  del st.session_state[var]
50
49
 
51
50
 
51
+ def highlight_row(row, row_index):
52
+ if row.name.strftime('%Y-%m-%dT%H:%M:%S.%f') == row_index.strftime('%Y-%m-%dT%H:%M:%S.%f').values[0]:
53
+ return ['background-color: lightpink']*len(row)
54
+ else:
55
+ return ['']*len(row)
56
+
57
+
52
58
  def footer_text():
53
59
  st.subheader('About this application:')
54
60
  st.markdown("""
@@ -65,16 +71,23 @@ def footer_text():
65
71
  right.markdown("""
66
72
  **Github**: Find the latest version here
67
73
  [![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/AthKouloumvakos/PyThea) \n
68
- **Citation**: Cite PyThea as [![https://doi.org/10.5281/zenodo.5713659](https://zenodo.org/badge/DOI/10.5281/zenodo.5713659.svg)](https://doi.org/10.5281/zenodo.5713659) \n
74
+ **Documentation Page**: https://www.pythea.org/
69
75
  """ +
70
76
  f"""
71
77
  **Version**: {version} (latest release [![Version](https://img.shields.io/github/v/release/AthKouloumvakos/PyThea)](https://github.com/AthKouloumvakos/PyThea/releases))
72
78
  """)
73
79
  left.image('https://github.com/AthKouloumvakos/PyThea/blob/master/docs/logo/pythea_logo.png?raw=true')
80
+ st.markdown("""
81
+ **Citation**: Please cite the following paper [![https://www.frontiersin.org/articles/10.3389/fspas.2022.974137/](https://img.shields.io/static/v1?label=Paper&message=Frontiers&color=red)](https://www.frontiersin.org/articles/10.3389/fspas.2022.974137/) and [![https://doi.org/10.5281/zenodo.5713659](https://zenodo.org/badge/DOI/10.5281/zenodo.5713659.svg)](https://doi.org/10.5281/zenodo.5713659)
82
+ """)
83
+ st.info('''
84
+ More imaging data have been added:
85
+ - SDO/AIA images from 211A channel have been added.
86
+ ''', icon='ℹ️')
74
87
  st.warning('''
75
- ⚠️ **NOTE: From PyThea >0.8.1 the JSON fitting files will be slightly different from the old ones.** ⚠️
76
- * Due to a change in the fitting time input, the new fitting files may have slightly different times for the same images (see further information [here](https://github.com/AthKouloumvakos/PyThea/discussions/24)).
77
- ''')
88
+ **NOTE: From PyThea >0.8.1 the JSON fitting files will be slightly different from the old ones.**
89
+ Due to a change in the fitting time input, the new fitting files may have slightly different times for the same images (see further information [here](https://github.com/AthKouloumvakos/PyThea/discussions/24)).
90
+ ''', icon='⚠️')
78
91
  st.markdown('---')
79
92
 
80
93
 
@@ -86,7 +99,10 @@ def run():
86
99
  #############################################################
87
100
  # set page config
88
101
  st.set_page_config(page_title='PyThea', page_icon=':rocket:',
89
- initial_sidebar_state='expanded')
102
+ initial_sidebar_state='expanded',
103
+ menu_items={
104
+ 'Get Help': 'https://www.pythea.org/',
105
+ 'Report a Bug': 'https://github.com/AthKouloumvakos/PyThea'})
90
106
 
91
107
  #############################################################
92
108
  # HTML Styles
@@ -94,7 +110,7 @@ def run():
94
110
 
95
111
  #############################################################
96
112
  # Main page information text
97
- st.title('PyThea: Reconstruct CMEs & Shocks')
113
+ st.header('PyThea: Reconstruct CMEs & Shocks')
98
114
 
99
115
  #############################################################
100
116
  # Startup Variables
@@ -106,7 +122,6 @@ def run():
106
122
 
107
123
  if 'date_process' not in st.session_state:
108
124
  date_and_event_selection(st)
109
- st.markdown(""" #### ⏻ Select a day & solar event. """)
110
125
  else:
111
126
  st.sidebar.markdown('## Processing Event|Date:')
112
127
  st.sidebar.info(f'{st.session_state.event_selected}')
@@ -194,7 +209,8 @@ def run():
194
209
  on_change=delete_from_state,
195
210
  kwargs={'vars': ['map', 'imagers_list_', 'clim', 'clim_manual_low', 'clim_manual_high']})
196
211
  if image_mode in ['Running Diff.', 'Base Diff.']:
197
- diff_value = procoption_container.number_input('Select Step/Image for Running/Base Diff.', 1, 5, key='diff_value',
212
+ min_diff = 1 if image_mode == 'Running Diff.' else 0
213
+ diff_value = procoption_container.number_input('Select Step/Image for Running/Base Diff.', min_diff, 5, key='diff_value',
198
214
  on_change=delete_from_state,
199
215
  kwargs={'vars': ['map', 'imagers_list_', 'clim', 'clim_manual_low', 'clim_manual_high']})
200
216
  else:
@@ -245,15 +261,16 @@ def run():
245
261
  st.session_state.map_ = {} if 'map_' not in st.session_state else st.session_state.map_
246
262
  st.session_state.map = {} if 'map' not in st.session_state else st.session_state.map
247
263
  st.session_state['imagers_list_'] = imagers_list
248
- progress_bar = stqdm.stqdm(imager_added, desc='Preparing to Download data')
249
- for imager in progress_bar:
250
- progress_bar.desc = f'Downloaded {imager} images from VSO'
264
+ progress_bar = st.progress(0, text='Preparing to Download data')
265
+ for i, imager in enumerate(imager_added):
266
+ progress_bar.progress(i/len(imager_added), text=f'Download {imager} images from VSO')
251
267
  if imager not in st.session_state.map_:
252
268
  timerange = a.Time(st.session_state.date_process + datetime.timedelta(hours=imaging_time_range[0]),
253
269
  st.session_state.date_process + datetime.timedelta(hours=imaging_time_range[1]))
254
- st.session_state.map_[imager] = download_fits(timerange, imager)
270
+ downloaded_files = download_fits(timerange, imager)
271
+ st.session_state.map_[imager] = load_fits(downloaded_files)
255
272
  st.session_state.map_[imager] = single_imager_maps_process(st.session_state.map_[imager],
256
- **selected_imagers.imager_dict[imager][1],
273
+ **selected_imagers.imager_dict[imager]['process'],
257
274
  skip='sequence_processing')
258
275
  processed_images = single_imager_maps_process(st.session_state.map_[imager],
259
276
  skip=['filter', 'prepare'],
@@ -265,6 +282,7 @@ def run():
265
282
  else:
266
283
  st.session_state.imagers_list_.remove(imager)
267
284
  st.session_state.map_colormap_limits.pop(imager, None)
285
+ progress_bar.empty()
268
286
 
269
287
  if imager_removed != []:
270
288
  st.session_state['imagers_list_'] = imagers_list
@@ -374,6 +392,7 @@ def run():
374
392
  # Store the fitting
375
393
  single_fit = model.to_dataframe()
376
394
  single_fit['imager'] = imager_select
395
+ single_fit['fits_file'] = running_map.meta['fits_file']
377
396
 
378
397
  if store_fit_button_pressed:
379
398
  if 'model_fittings' not in st.session_state:
@@ -390,10 +409,13 @@ def run():
390
409
  st.markdown('---')
391
410
  st.markdown('### Parameters Table')
392
411
  st.markdown('**Running Fitting Table:**')
393
- st.dataframe(single_fit)
412
+ col_formats = {col: '{:,.2f}'.format for col in single_fit.select_dtypes(include='number').columns}
413
+ st.dataframe(single_fit.style.format(col_formats))
394
414
  if 'model_fittings' in st.session_state:
395
415
  st.markdown('**Stored Fitting Table:**')
396
- st.dataframe(st.session_state.model_fittings.parameters)
416
+ st.dataframe(st.session_state.model_fittings.parameters.style.apply(highlight_row,
417
+ row_index=single_fit.index, axis=1).format(col_formats)
418
+ )
397
419
  col1, col2 = st.columns((2, 2))
398
420
  col2.selectbox('Select a fitting',
399
421
  options=st.session_state.model_fittings.parameters.index,
@@ -413,7 +435,7 @@ def run():
413
435
  st.markdown('### Plots of kinematics ')
414
436
  col1, col2, col3 = st.columns(3)
415
437
  plt_kinematics_select = col1.selectbox('Select Plots',
416
- options=['All', 'HeightT', 'SpeedT', 'Long-LatT'])
438
+ options=['All', 'HeightT', 'SpeedT', 'AccelerationT', 'Long-LatT'])
417
439
 
418
440
  fit_mode = col2.selectbox('Select Fitting Mode',
419
441
  options=['polynomial', 'spline', 'custom'],
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.11.0'
16
- __version_tuple__ = version_tuple = (0, 11, 0)
15
+ __version__ = version = '0.12.0'
16
+ __version_tuple__ = version_tuple = (0, 12, 0)
@@ -1,9 +1,4 @@
1
1
  def apply(st):
2
- # Hide the menu button
3
- st.markdown(""" <style>
4
- #MainMenu {visibility: hidden;}
5
- footer {visibility: hidden;}
6
- </style> """, unsafe_allow_html=True)
7
2
  # Do some css styling tricks here (e.g. remove the padding)
8
3
  # https://discuss.streamlit.io/t/reduce-white-space-top-of-the-page/21737/3
9
4
  st.markdown("""
@@ -0,0 +1,65 @@
1
+ '''
2
+ A dictionary of the selected imagers
3
+ How to use this:
4
+
5
+ '''
6
+ import astropy.units as u
7
+ from sunpy.net import attrs as a
8
+
9
+ imager_dict = {}
10
+
11
+ imager_dict['LC2'] = {'fido': (a.Instrument.lasco, a.Detector.c2),
12
+ 'process': {'dimensions': (1024*u.pixel, 1024*u.pixel), 'polar': 'Clear', 'superpixel': 2},
13
+ 'source': 'SOHO', 'instrument': 'LASCO', 'detector': 'C2'}
14
+
15
+ imager_dict['LC3'] = {'fido': (a.Instrument.lasco, a.Detector.c3),
16
+ 'process': {'dimensions': (1024*u.pixel, 1024*u.pixel), 'polar': 'Clear', 'superpixel': 2},
17
+ 'source': 'SOHO', 'instrument': 'LASCO', 'detector': 'C3'}
18
+
19
+ imager_dict['AIA-193'] = {'fido': (a.Instrument.aia, a.Wavelength(19.3 * u.nm), a.Sample(1*u.minute)),
20
+ 'process': {'dimensions': (4096*u.pixel, 4096*u.pixel), 'superpixel': 8, 'exposure': 1.90},
21
+ 'source': 'SDO', 'instrument': 'AIA', 'wavelength': '193'}
22
+
23
+ imager_dict['AIA-211'] = {'fido': (a.Instrument.aia, a.Wavelength(21.1 * u.nm), a.Sample(1*u.minute)),
24
+ 'process': {'dimensions': (4096*u.pixel, 4096*u.pixel), 'superpixel': 8, 'exposure': 1.90},
25
+ 'source': 'SDO', 'instrument': 'AIA', 'wavelength': '211'}
26
+
27
+ imager_dict['COR2A'] = {'fido': (a.Source('STEREO_A'), a.Detector.cor2),
28
+ 'process': {'dimensions': (2048*u.pixel, 2048*u.pixel), 'polar': 1001, 'superpixel': 4},
29
+ 'source': 'STEREO_A', 'instrument': 'SECCHI', 'detector': 'COR2'}
30
+
31
+ imager_dict['COR2B'] = {'fido': (a.Source('STEREO_B'), a.Detector.cor2),
32
+ 'process': {'dimensions': (2048*u.pixel, 2048*u.pixel), 'polar': 1001, 'superpixel': 4},
33
+ 'source': 'STEREO_B', 'instrument': 'SECCHI', 'detector': 'COR2'}
34
+
35
+ imager_dict['EUVIA'] = {'fido': (a.Source('STEREO_A'), a.Detector.euvi, a.Wavelength(19.5 * u.nm)),
36
+ 'process': {'dimensions': (2048*u.pixel, 2048*u.pixel), 'superpixel': 4},
37
+ 'source': 'STEREO_A', 'instrument': 'SECCHI', 'detector': 'EUVI'}
38
+
39
+ imager_dict['EUVIB'] = {'fido': (a.Source('STEREO_B'), a.Detector.euvi, a.Wavelength(19.5 * u.nm)),
40
+ 'process': {'dimensions': (2048*u.pixel, 2048*u.pixel), 'superpixel': 4},
41
+ 'source': 'STEREO_B', 'instrument': 'SECCHI', 'detector': 'EUVI'}
42
+
43
+ imager_dict['COR1A'] = {'fido': (a.Source('STEREO_A'), a.Detector.cor1),
44
+ 'process': {'dimensions': (512*u.pixel, 512*u.pixel)},
45
+ 'source': 'STEREO_A', 'instrument': 'SECCHI', 'detector': 'COR1'}
46
+
47
+ imager_dict['COR1B'] = {'fido': (a.Source('STEREO_B'), a.Detector.cor1),
48
+ 'process': {'dimensions': (512*u.pixel, 512*u.pixel)},
49
+ 'source': 'STEREO_B', 'instrument': 'SECCHI', 'detector': 'COR1'}
50
+
51
+ imager_dict['HI1A'] = {'fido': (a.Source('STEREO_A'), a.Detector.hi1),
52
+ 'process': {'dimensions': (1024*u.pixel, 1024*u.pixel), 'superpixel': 2},
53
+ 'source': 'STEREO_A', 'instrument': 'SECCHI', 'detector': 'HI1'}
54
+
55
+ imager_dict['HI1B'] = {'fido': (a.Source('STEREO_B'), a.Detector.hi1),
56
+ 'process': {'dimensions': (1024*u.pixel, 1024*u.pixel), 'superpixel': 2},
57
+ 'source': 'STEREO_B', 'instrument': 'SECCHI', 'detector': 'HI1'}
58
+
59
+ imager_dict['HI2A'] = {'fido': (a.Source('STEREO_A'), a.Detector.hi2),
60
+ 'process': {'dimensions': (1024*u.pixel, 1024*u.pixel), 'superpixel': 2},
61
+ 'source': 'STEREO_A', 'instrument': 'SECCHI', 'detector': 'HI2'}
62
+
63
+ imager_dict['HI2B'] = {'fido': (a.Source('STEREO_B'), a.Detector.hi2),
64
+ 'process': {'dimensions': (1024*u.pixel, 1024*u.pixel), 'superpixel': 2},
65
+ 'source': 'STEREO_B', 'instrument': 'SECCHI', 'detector': 'HI2'}
@@ -30,6 +30,6 @@ json_fitting_file_sample_data = pooch.create(
30
30
  path=os.path.join(database_dir, 'sample_data'), # The cache folder
31
31
  base_url=f'{github_main_url}/raw/main/data/', # The remote data url on Github
32
32
  registry={
33
- 'FLX1p0D20211028T153500MEllipsoid.json': 'sha256:700687ed982317400ec409390571747694237de9688a2816baa7b1770b75c9b1',
33
+ 'FLX1p0D20211028T153500MEllipsoid.json': 'sha256:34fced8530875110117ba27a73541d3acd0c90bc8fca99367c1ec4cdfc05ce86',
34
34
  },
35
35
  )
@@ -8,6 +8,7 @@ import warnings
8
8
  import astropy.units as u
9
9
  import numpy as np
10
10
  import sunpy.map
11
+ from sunpy.map.mapsequence import MapSequence
11
12
 
12
13
  import PyThea.sunpy_dev.extern.sunkit_instruments.aia.utils # noqa
13
14
  import PyThea.sunpy_dev.extern.sunkit_instruments.lasco.utils # noqa
@@ -47,7 +48,7 @@ def maps_sequence_processing(map_sequence, **kwargs):
47
48
 
48
49
  smap = []
49
50
  if seq_type == 'Running Diff.':
50
- for i in range(1+diff_num, len(map_sequence)):
51
+ for i in range(diff_num, len(map_sequence)):
51
52
  smap_diff = difference_maps(map_sequence[i], map_sequence[i-diff_num])
52
53
  smap.append(smap_diff)
53
54
  if seq_type == 'Base Diff.':
@@ -151,7 +152,11 @@ def filter_maps(map_sequence, **kwargs):
151
152
  map_sequence = [tmap for tmap in map_sequence if tmap.meta['polar'] == kwargs['polar']]
152
153
 
153
154
  if len(map_sequence) != 0:
154
- sequence_final = sunpy.map.Map(map_sequence, sequence=True)
155
+ if isinstance(map_sequence, MapSequence):
156
+ return map_sequence
157
+ else:
158
+ sequence_final = sunpy.map.Map(map_sequence, sequence=True)
159
+
155
160
  else:
156
161
  sequence_final = []
157
162
 
@@ -2,5 +2,6 @@
2
2
  "PyThea.test.test_figures.test_ellipsoid_on_AIA_venus": "f1ff774b483a8c934c9353c552278c8823216fc7d9dad4ccc00c74be3f30c4c3",
3
3
  "PyThea.test.test_figures.test_ellipsoid_on_AIA_mercury": "f6afda1c769a061b7ab1fc64c4e9c0f4658cdb97c3be83828ba5d98bf1bb182c",
4
4
  "PyThea.test.test_figures.test_ellipsoid_on_STEREO_COR1_venus": "18a3af72e9da5b60e435f83ee3ef3f8cd0eb437eaef463329552ff56968f12ff",
5
- "PyThea.test.test_figures.test_ellipsoid_on_STEREO_COR2_three_planets": "231d5635f57c4d66556674a83f6cbcef7dc94b51846e977c4c2dc3dc244096ac"
5
+ "PyThea.test.test_figures.test_ellipsoid_on_STEREO_COR2_three_planets": "231d5635f57c4d66556674a83f6cbcef7dc94b51846e977c4c2dc3dc244096ac",
6
+ "PyThea.test.test_figures.test_kinematics_figure": "83e060de53b57e9d34fe50111ba60a44f7c7c7b20faae9a4381654ef1c9ea72d"
6
7
  }
@@ -5,9 +5,12 @@ import sunpy.map
5
5
  from astropy.coordinates import SkyCoord, solar_system_ephemeris
6
6
  from sunpy.coordinates import get_body_heliographic_stonyhurst
7
7
 
8
- from PyThea.data.sample_data import aia_sample_data, stereo_sample_data
8
+ from PyThea.data.sample_data import (aia_sample_data,
9
+ json_fitting_file_sample_data,
10
+ stereo_sample_data)
9
11
  from PyThea.geometrical_models import ellipsoid
10
12
  from PyThea.sunpy_dev.map.maputils import prepare_maps
13
+ from PyThea.utils import model_fittings, plot_fitting_model
11
14
 
12
15
  solar_system_ephemeris.set('de432s')
13
16
 
@@ -167,3 +170,27 @@ def test_ellipsoid_on_STEREO_COR2_three_planets():
167
170
  fig.subplots_adjust(hspace=0.5, wspace=0.35)
168
171
 
169
172
  return fig
173
+
174
+
175
+ @pytest.mark.mpl_image_compare()
176
+ def test_kinematics_figure():
177
+ json_fitting_file = json_fitting_file_sample_data.fetch('FLX1p0D20211028T153500MEllipsoid.json')
178
+ model_fittings_class = model_fittings.load_from_json(json_fitting_file)
179
+
180
+ fit_method = {'type': 'polynomial', 'order': 2}
181
+
182
+ fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(18, 5), tight_layout=True)
183
+
184
+ fig, ax1 = plot_fitting_model(model_fittings_class,
185
+ fit_args=fit_method,
186
+ plt_type='HeightT',
187
+ fig=fig, axis=ax1)
188
+ fig, ax2 = plot_fitting_model(model_fittings_class,
189
+ fit_args=fit_method,
190
+ plt_type='SpeedT',
191
+ fig=fig, axis=ax2)
192
+ fig, ax3 = plot_fitting_model(model_fittings_class,
193
+ fit_args=fit_method,
194
+ plt_type='AccelerationT',
195
+ fig=fig, axis=ax3)
196
+ return fig
@@ -68,7 +68,7 @@ def test_vso_search(imager):
68
68
  """
69
69
  Tests that the Fido.search returns always the same number of files from VSO.
70
70
  """
71
- file_num = {'AIA': [60, 61],
71
+ file_num = {'AIA-193': [60, 61], 'AIA-211': [60, 61],
72
72
  'LC2': [5], 'LC3': [5],
73
73
  'COR2A': [7], 'COR2B': [7],
74
74
  'EUVIA': [11], 'EUVIB': [11],
@@ -79,7 +79,7 @@ def test_vso_search(imager):
79
79
  for query in [a.Time('2011/01/01 00:00:00', '2011/01/01 01:00:00'),
80
80
  a.Time('2012/01/01 00:00:00', '2012/01/01 01:00:00'),
81
81
  a.Time('2013/01/01 00:00:00', '2013/01/01 01:00:00'), ]:
82
- args = imager_dict[imager][0]
82
+ args = imager_dict[imager]['fido']
83
83
  result = Fido.search(query, *args)
84
84
 
85
85
  assert len(result) == 1
@@ -174,15 +174,32 @@ def download_fits(timerange, imager):
174
174
  '''
175
175
  Downloads the imaging data (fits files) from VSO
176
176
  '''
177
- maps_ = []
178
- args = imager_dict[imager][0]
179
- result = Fido.search(timerange, *args)
177
+ imager_prop = imager_dict[imager]
178
+ result = Fido.search(timerange, *imager_prop['fido'])
180
179
  print(result)
181
180
  if result:
182
- downloaded_files = Fido.fetch(result, path=f'{database_dir}'+'/data/{source}/{instrument}/'+'/{file}')
183
- for file_path in downloaded_files:
181
+ if 'detector' in imager_prop:
182
+ sub_path = imager_prop['detector']
183
+ elif 'wavelength' in imager_prop:
184
+ sub_path = imager_prop['wavelength']
185
+ path_str = f'{database_dir}/data/{imager_prop["source"]}/{imager_prop["instrument"]}/{sub_path}'+'/{file}'
186
+ downloaded_files = Fido.fetch(result, path=path_str)
187
+ else:
188
+ downloaded_files = []
189
+
190
+ return downloaded_files
191
+
192
+
193
+ def load_fits(files):
194
+ '''
195
+ Loads the imaging data (fits files) from a list of files.
196
+ '''
197
+ maps_ = []
198
+ if files:
199
+ for file_path in files:
184
200
  try:
185
201
  map_ = sunpy.map.Map(file_path)
202
+ map_.meta['fits_file'] = os.path.basename(file_path)
186
203
  maps_.append(map_)
187
204
  except RuntimeError as err:
188
205
  print('Handling RuntimeError error:', err)
@@ -192,7 +209,6 @@ def download_fits(timerange, imager):
192
209
  print(f"File '{file_path}' has been removed.")
193
210
  if maps_:
194
211
  maps_ = sunpy.map.Map(maps_, sequence=True)
195
-
196
212
  return maps_
197
213
 
198
214
 
@@ -210,7 +226,7 @@ def maps_process(maps_dict_in, imagers_list_in, image_mode, **kwargs):
210
226
  for imager in imagers_list_in:
211
227
  if imager in maps_dict_in and maps_dict_in[imager] != []:
212
228
  if not kwargs:
213
- extras = imager_dict[imager][1]
229
+ extras = imager_dict[imager]['process']
214
230
  else:
215
231
  if imager in kwargs:
216
232
  extras = kwargs[imager]
@@ -277,6 +293,14 @@ class model_fittings:
277
293
  the old file with the new one. This will not alter your fittings.')
278
294
  kinematics = {'fit_method': {'type': 'polynomial', 'order': 1}}
279
295
 
296
+ if fitting['version'] <= '0.11.0':
297
+ # In version >0.11.0 more AIA channels added so this will update the fitting files
298
+ # prodused at earlier versions by replasing the imager values from "AIA" to "AIA-193".
299
+ parameters['imager'] = parameters['imager'].replace('AIA', 'AIA-193')
300
+ # In version >0.11.0 the fits file name is added to the single fits
301
+ if 'fits_file' not in parameters.columns:
302
+ parameters['fits_file'] = ''
303
+
280
304
  model_fittings_class = model_fittings(fitting['event_selected'],
281
305
  fitting['date_process'],
282
306
  fitting['geometrical_model']['type'],
@@ -315,11 +339,15 @@ class model_fittings:
315
339
  return json.dumps(model_dict, indent=' ')
316
340
 
317
341
 
318
- def plot_fitting_model(model, fit_args, plt_type='HeightT'):
342
+ def plot_fitting_model(model, fit_args, plt_type='HeightT', fig=None, axis=None):
319
343
  '''
320
344
  Plot the height(speed)--time evolution of the fitting parameters.
321
345
  '''
322
346
  palete = sns.color_palette('deep')
347
+
348
+ Rs2km = (1 * u.R_sun).to_value(u.km)
349
+ sec = 24*60*60
350
+
323
351
  parameters = {
324
352
  'Spheroid':
325
353
  {'height': ['+', '', palete[3], 'h-apex'],
@@ -335,9 +363,14 @@ def plot_fitting_model(model, fit_args, plt_type='HeightT'):
335
363
  'rapex': ['x', '', palete[0], 'r-apex'],
336
364
  },
337
365
  }
366
+
338
367
  parameters = parameters[model.geometrical_model]
339
- # Height vs time
340
- fig, axis = plt.subplots(figsize=(5.5, 5.5), tight_layout=True)
368
+
369
+ if fig is None and axis is None:
370
+ fig, axis = plt.subplots(figsize=(5.5, 5.5), tight_layout=True)
371
+ else:
372
+ fig, axis = fig, axis
373
+
341
374
  if plt_type == 'HeightT':
342
375
  for p in parameters.keys():
343
376
  axis.plot(model.parameters.index,
@@ -345,7 +378,7 @@ def plot_fitting_model(model, fit_args, plt_type='HeightT'):
345
378
  marker=parameters[p][0],
346
379
  linestyle=parameters[p][1],
347
380
  color=parameters[p][2],
348
- label=parameters[p][3]) # label='fit: a=%5.3f, b=%5.3f, c=%5.3f' % tuple(popt)
381
+ label=parameters[p][3])
349
382
  if len(model.parameters[p])-1 > fit_args['order']:
350
383
  # How to get confidence intervals from curve_fit?
351
384
  fit = parameter_fit(model.parameters.index, model.parameters[p], fit_args)
@@ -359,26 +392,45 @@ def plot_fitting_model(model, fit_args, plt_type='HeightT'):
359
392
  axis.plot(model.parameters.index, model.parameters[p], '--', color=parameters[p][2])
360
393
  ylabel = 'Height of apex and length of flanks [Rsun]'
361
394
  axis.set_ylim(bottom=0)
362
- elif plt_type == 'SpeedT':
395
+ elif plt_type in ('SpeedT', 'AccelerationT'):
396
+ gradient_power = {'SpeedT': 1, 'AccelerationT': 2}
397
+ const = {'SpeedT': Rs2km/sec, 'AccelerationT': Rs2km/sec**2}
363
398
  for p in parameters.keys():
364
- if len(model.parameters[p])-1 > fit_args['order']:
399
+ if len(model.parameters[p])-gradient_power[plt_type] > fit_args['order']:
365
400
  # How to get confidence intervals from curve_fit?
366
401
  fit = parameter_fit(model.parameters.index, model.parameters[p], fit_args)
367
- Rs2km = (1 * u.R_sun).to_value(u.km)
368
- sec = 24*60*60
369
- speed_best_fit = (Rs2km/sec) * np.gradient(fit['best_fit_y'], fit['best_fit_x_num'])
370
- speed_bound_upper = (Rs2km/sec) * np.gradient(fit['sigma_bounds']['up'], fit['best_fit_x_num'])
371
- speed_bound_lower = (Rs2km/sec) * np.gradient(fit['sigma_bounds']['low'], fit['best_fit_x_num'])
372
- axis.plot(fit['best_fit_x'], speed_best_fit, '-', color=parameters[p][2], label=parameters[p][3])
373
- axis.fill_between(fit['best_fit_x'], speed_bound_lower, speed_bound_upper,
402
+ if plt_type == 'SpeedT':
403
+ best_fit = const[plt_type] * np.gradient(fit['best_fit_y'], fit['best_fit_x_num'])
404
+ upper_bound = const[plt_type] * np.gradient(fit['sigma_bounds']['up'], fit['best_fit_x_num'])
405
+ lower_bound = const[plt_type] * np.gradient(fit['sigma_bounds']['low'], fit['best_fit_x_num'])
406
+ if fit_args['type'] == 'spline':
407
+ axis.fill_between(fit['best_fit_x'], const[plt_type] * fit['sigv_bounds']['dlow'], const[plt_type] * fit['sigv_bounds']['dup'],
408
+ color=parameters[p][2], alpha=0.05)
409
+ ylabel = 'Speed [km/s]'
410
+ elif plt_type == 'AccelerationT':
411
+ best_fit = const[plt_type] * np.gradient(np.gradient(fit['best_fit_y'], fit['best_fit_x_num'], edge_order=2), fit['best_fit_x_num'], edge_order=2)
412
+ upper_bound = const[plt_type] * np.gradient(np.gradient(fit['sigma_bounds']['up'], fit['best_fit_x_num'], edge_order=2), fit['best_fit_x_num'], edge_order=2)
413
+ lower_bound = const[plt_type] * np.gradient(np.gradient(fit['sigma_bounds']['low'], fit['best_fit_x_num'], edge_order=2), fit['best_fit_x_num'], edge_order=2)
414
+ if fit_args['type'] == 'spline':
415
+ axis.fill_between(fit['best_fit_x'], const[plt_type] * fit['sigv_bounds']['ddlow'], const[plt_type] * fit['sigv_bounds']['ddup'],
416
+ color=parameters[p][2], alpha=0.05)
417
+ ylabel = 'Acceleration [km/s$^2$]'
418
+
419
+ axis.plot(fit['best_fit_x'], best_fit, '-', color=parameters[p][2], label=parameters[p][3])
420
+ axis.fill_between(fit['best_fit_x'], lower_bound, upper_bound,
374
421
  color=parameters[p][2], alpha=0.20)
375
- if fit_args['type'] == 'spline':
376
- axis.fill_between(fit['best_fit_x'], (Rs2km/sec) * fit['sigv_bounds']['dlow'], (Rs2km/sec) * fit['sigv_bounds']['dup'],
377
- color=parameters[p][2], alpha=0.05)
422
+
378
423
  else:
379
- pass
380
- ylabel = 'Speed [km/s]'
424
+ ylabel = ' '
425
+ axis.text(0.5, 0.5, f'Not enough points for \n fitting with order {fit_args["order"]}.',
426
+ transform=axis.transAxes,
427
+ fontsize=20, color='gray', alpha=0.5,
428
+ ha='center', va='center', rotation=30)
429
+ break
430
+
431
+ if plt_type != 'AccelerationT':
381
432
  axis.set_ylim(bottom=0)
433
+
382
434
  if plt_type == 'LongT' or plt_type == 'LatT':
383
435
  parameters = {'LongT': ['hgln', '+', palete[3], 'Longitude'],
384
436
  'LatT': ['hglt', '+', palete[2], 'Latitude']}
@@ -411,8 +463,16 @@ def plot_fitting_model(model, fit_args, plt_type='HeightT'):
411
463
  axis.xaxis.set_major_formatter(formatter)
412
464
  axis.minorticks_on()
413
465
  xlim = axis.get_xlim()
414
- if xlim[1] - xlim[0] <= 0.5:
415
- axis.xaxis.set_minor_locator(mdates.MinuteLocator(byminute=[0, 10, 20, 30, 40, 50]))
466
+
467
+ hour_threshold = 24 * (xlim[1] - xlim[0])
468
+
469
+ if hour_threshold <= 2:
470
+ axis.xaxis.set_minor_locator(mdates.MinuteLocator(byminute=np.arange(0, 61, 1)))
471
+ elif hour_threshold <= 6:
472
+ axis.xaxis.set_minor_locator(mdates.MinuteLocator(byminute=np.arange(0, 61, 5)))
473
+ else:
474
+ axis.xaxis.set_minor_locator(mdates.HourLocator(byhour=np.arange(0, 25, 1)))
475
+
416
476
  fig.autofmt_xdate(bottom=0, rotation=0, ha='center')
417
477
  axis.legend(loc='lower right')
418
478
 
@@ -453,13 +513,17 @@ def parameter_fit(x, y, fit_args):
453
513
  sigma_bound_up = best_fit + sigma
454
514
  sigma_bound_low = best_fit - sigma
455
515
 
456
- sv_bound_up, sv_bound_low, sv_bound_dup, sv_bound_dlow = best_fit, best_fit, np.gradient(best_fit, xxx), np.gradient(best_fit, xxx)
516
+ sv_bound_up, sv_bound_low, sv_bound_dup, sv_bound_dlow, sv_bound_ddup, sv_bound_ddlow = \
517
+ best_fit, best_fit, np.gradient(best_fit, xxx), np.gradient(best_fit, xxx), \
518
+ np.gradient(np.gradient(best_fit, xxx)), np.gradient(np.gradient(best_fit, xxx))
457
519
  for i in range(2, 100):
458
520
  spl = UnivariateSpline(xx, y, s=i/100, k=fit_args['order'])
459
521
  sv_bound_up = np.maximum(sv_bound_up, spl(xxx))
460
522
  sv_bound_low = np.minimum(sv_bound_low, spl(xxx))
461
523
  sv_bound_dup = np.maximum(sv_bound_dup, np.gradient(spl(xxx), xxx))
462
524
  sv_bound_dlow = np.minimum(sv_bound_dlow, np.gradient(spl(xxx), xxx))
525
+ sv_bound_ddup = np.maximum(sv_bound_ddup, np.gradient(np.gradient(spl(xxx), xxx)))
526
+ sv_bound_ddlow = np.minimum(sv_bound_ddlow, np.gradient(np.gradient(spl(xxx), xxx)))
463
527
 
464
528
  fitting = {'spl': spl,
465
529
  'sigma': sigma,
@@ -471,7 +535,9 @@ def parameter_fit(x, y, fit_args):
471
535
  'sigv_bounds': {'up': sv_bound_up,
472
536
  'low': sv_bound_low,
473
537
  'dup': sv_bound_dup,
474
- 'dlow': sv_bound_dlow},
538
+ 'dlow': sv_bound_dlow,
539
+ 'ddup': sv_bound_ddup,
540
+ 'ddlow': sv_bound_ddlow},
475
541
  }
476
542
  elif fit_args['type'] == 'custom':
477
543
  expression = fit_args['expression'] # 'a * exp(-b * x) + c'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyThea
3
- Version: 0.11.0
3
+ Version: 0.12.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
@@ -35,7 +35,6 @@ Requires-Dist: matplotlib
35
35
  Requires-Dist: seaborn
36
36
  Requires-Dist: streamlit
37
37
  Requires-Dist: Pillow
38
- Requires-Dist: stqdm
39
38
  Requires-Dist: lxml
40
39
  Requires-Dist: zeep
41
40
  Requires-Dist: drms
@@ -63,8 +62,8 @@ We recommend, creating a virtual environment for _PyThea_ and installing the pac
63
62
  If you use Anaconda or Miniconda (which we also recommend) you can create a virtual environment using ```conda``` and then install _PyThea_ using from PyPI using ```pip```. In the terminal do the following:
64
63
 
65
64
  ```python
66
- # Create a virtual environment. Use python=3.8 or 3.9
67
- conda create --name PyThea python=3.9
65
+ # Create a virtual environment. Use python>3.9
66
+ conda create --name PyThea python=3.10
68
67
 
69
68
  # Activate the environment
70
69
  conda activate PyThea
@@ -138,7 +137,7 @@ If there is an error when running ```PyThea streamlit``` then you can manually r
138
137
 
139
138
  ## 📙 Usage
140
139
 
141
- Complete documentation of the _PyThea_ is under construction.
140
+ Complete documentation of the _PyThea_ can be found in [https://www.pythea.org/](https://www.pythea.org/).
142
141
 
143
142
  ## 📦 Useful Python packages
144
143
 
@@ -1,3 +1,4 @@
1
+ .readthedocs.yaml
1
2
  CHANGELOG.md
2
3
  LICENSE.md
3
4
  MANIFEST.in
@@ -13,7 +13,6 @@ matplotlib
13
13
  seaborn
14
14
  streamlit
15
15
  Pillow
16
- stqdm
17
16
  lxml
18
17
  zeep
19
18
  drms
@@ -22,8 +22,8 @@ We recommend, creating a virtual environment for _PyThea_ and installing the pac
22
22
  If you use Anaconda or Miniconda (which we also recommend) you can create a virtual environment using ```conda``` and then install _PyThea_ using from PyPI using ```pip```. In the terminal do the following:
23
23
 
24
24
  ```python
25
- # Create a virtual environment. Use python=3.8 or 3.9
26
- conda create --name PyThea python=3.9
25
+ # Create a virtual environment. Use python>3.9
26
+ conda create --name PyThea python=3.10
27
27
 
28
28
  # Activate the environment
29
29
  conda activate PyThea
@@ -97,7 +97,7 @@ If there is an error when running ```PyThea streamlit``` then you can manually r
97
97
 
98
98
  ## 📙 Usage
99
99
 
100
- Complete documentation of the _PyThea_ can be found in (under construction)
100
+ Complete documentation of the _PyThea_ can be found in [https://www.pythea.org/](https://www.pythea.org/).
101
101
 
102
102
  ## 📦 Useful Python packages
103
103
 
@@ -16,8 +16,8 @@ We recommend, creating a virtual environment for _PyThea_ and installing the pac
16
16
  If you use Anaconda or Miniconda (which we also recommend) you can create a virtual environment using ```conda``` and then install _PyThea_ using from PyPI using ```pip```. In the terminal do the following:
17
17
 
18
18
  ```python
19
- # Create a virtual environment. Use python=3.8 or 3.9
20
- conda create --name PyThea python=3.9
19
+ # Create a virtual environment. Use python>3.9
20
+ conda create --name PyThea python=3.10
21
21
 
22
22
  # Activate the environment
23
23
  conda activate PyThea
@@ -91,7 +91,7 @@ If there is an error when running ```PyThea streamlit``` then you can manually r
91
91
 
92
92
  ## 📙 Usage
93
93
 
94
- Complete documentation of the _PyThea_ is under construction.
94
+ Complete documentation of the _PyThea_ can be found in [https://www.pythea.org/](https://www.pythea.org/).
95
95
 
96
96
  ## 📦 Useful Python packages
97
97
 
@@ -26,5 +26,4 @@ dependencies:
26
26
  - pip
27
27
  - pip:
28
28
  - pooch
29
- - stqdm
30
29
  - jplephem
@@ -13,7 +13,6 @@ matplotlib
13
13
  seaborn
14
14
  streamlit
15
15
  Pillow
16
- stqdm
17
16
  lxml
18
17
  zeep
19
18
  drms
@@ -34,6 +34,10 @@ exclude =
34
34
  .md,
35
35
  PyThea/extensions/
36
36
 
37
+ [tool:pytest]
38
+ addopts =
39
+ --ignore=docs/
40
+
37
41
  [egg_info]
38
42
  tag_build =
39
43
  tag_date = 0
@@ -1,34 +0,0 @@
1
- '''
2
- A dictionary of the selected imagers
3
- How to use this:
4
-
5
- '''
6
- import astropy.units as u
7
- from sunpy.net import attrs as a
8
-
9
- imager_dict = dict.fromkeys(['LC2'], [(a.Instrument.lasco, a.Detector.c2),
10
- {'dimensions': (1024*u.pixel, 1024*u.pixel), 'polar': 'Clear', 'superpixel': 2}, 'LASCO-C2'])
11
- imager_dict.update(dict.fromkeys(['LC3'], [(a.Instrument.lasco, a.Detector.c3),
12
- {'dimensions': (1024*u.pixel, 1024*u.pixel), 'polar': 'Clear', 'superpixel': 2}, 'LASCO-C3']))
13
- imager_dict.update(dict.fromkeys(['AIA'], [(a.Instrument.aia, a.Wavelength(19.3 * u.nm), a.Sample(1*u.minute)),
14
- {'dimensions': (4096*u.pixel, 4096*u.pixel), 'superpixel': 8, 'exposure': 1.90}, 'SDO-AIA']))
15
- imager_dict.update(dict.fromkeys(['COR2A'], [(a.Source('STEREO_A'), a.Detector.cor2),
16
- {'dimensions': (2048*u.pixel, 2048*u.pixel), 'polar': 1001, 'superpixel': 4}, 'STA-COR2']))
17
- imager_dict.update(dict.fromkeys(['COR2B'], [(a.Source('STEREO_B'), a.Detector.cor2),
18
- {'dimensions': (2048*u.pixel, 2048*u.pixel), 'polar': 1001, 'superpixel': 4}, 'STB-COR2']))
19
- imager_dict.update(dict.fromkeys(['EUVIA'], [(a.Source('STEREO_A'), a.Detector.euvi, a.Wavelength(19.5 * u.nm)),
20
- {'dimensions': (2048*u.pixel, 2048*u.pixel), 'superpixel': 4}, 'STA-EUVI']))
21
- imager_dict.update(dict.fromkeys(['EUVIB'], [(a.Source('STEREO_B'), a.Detector.euvi, a.Wavelength(19.5 * u.nm)),
22
- {'dimensions': (2048*u.pixel, 2048*u.pixel), 'superpixel': 4}, 'STB-EUVI']))
23
- imager_dict.update(dict.fromkeys(['COR1A'], [(a.Source('STEREO_A'), a.Detector.cor1),
24
- {'dimensions': (512*u.pixel, 512*u.pixel)}, 'STA-COR1'])) # 'polar':0
25
- imager_dict.update(dict.fromkeys(['COR1B'], [(a.Source('STEREO_B'), a.Detector.cor1),
26
- {'dimensions': (512*u.pixel, 512*u.pixel)}, 'STB-COR1'])) # 'polar':0
27
- imager_dict.update(dict.fromkeys(['HI1A'], [(a.Source('STEREO_A'), a.Detector.hi1),
28
- {'dimensions': (1024*u.pixel, 1024*u.pixel), 'superpixel': 2}, 'STA-HI1']))
29
- imager_dict.update(dict.fromkeys(['HI1B'], [(a.Source('STEREO_B'), a.Detector.hi1),
30
- {'dimensions': (1024*u.pixel, 1024*u.pixel), 'superpixel': 2}, 'STB-HI1']))
31
- imager_dict.update(dict.fromkeys(['HI2A'], [(a.Source('STEREO_A'), a.Detector.hi2),
32
- {'dimensions': (1024*u.pixel, 1024*u.pixel), 'superpixel': 2}, 'STA-HI2']))
33
- imager_dict.update(dict.fromkeys(['HI2B'], [(a.Source('STEREO_B'), a.Detector.hi2),
34
- {'dimensions': (1024*u.pixel, 1024*u.pixel)}, 'STB-HI2']))
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