Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • software_public/passoft/sohstationviewer
1 result
Show changes
Commits on Source (93)
Showing
with 277 additions and 226 deletions
......@@ -28,29 +28,29 @@ flake8:
- passoft
stage: Build Env and Test
script:
- flake8 --exclude sohstationviewer/view/ui,sohstationviewer/controller/core/ sohstationviewer
- flake8 --exclude sohstationviewer/view/ui,sohstationviewer/controller/core/,sohstationviewer/main.py
- flake8 tests
python3.7:
image: python:3.7
python3.9:
image: python:3.9
tags:
- passoft
stage: Build Env and Test
script:
- python -m unittest
python3.8:
image: python:3.8
python3.10:
image: python:3.10
tags:
- passoft
stage: Build Env and Test
script:
- python -m unittest
python3.9:
image: python:3.9
python3.11:
image: python:3.11
tags:
- passoft
stage: Build Env and Test
script:
- python -m unittest
- python -m unittest
=======
Credits
=======
Development Lead
----------------
* EPIC <software-support@passcal.nmt.edu>
Contributors
------------
None yet. Why not be the first?
.. highlight:: shell
============
Contributing
============
Contributions are welcome, and they are greatly appreciated! Every little bit
helps, and credit will always be given.
You can contribute in many ways:
Types of Contributions
----------------------
Report Bugs
~~~~~~~~~~~
Report bugs at https://git.passcal.nmt.edu/software_public/passoft/sohstationviewer/issues.
If you are reporting a bug, please include:
* Your operating system name and version.
* Any details about your local setup that might be helpful in troubleshooting.
* Detailed steps to reproduce the bug.
Fix Bugs
~~~~~~~~
Look through the GitHub issues for bugs. Anything tagged with "bug" and "help
wanted" is open to whoever wants to implement it.
Implement Features
~~~~~~~~~~~~~~~~~~
Look through the GitLab issues for features. Anything tagged with "enhancement"
and "help wanted" is open to whoever wants to implement it.
Write Documentation
~~~~~~~~~~~~~~~~~~~
SOHViewer could always use more documentation, whether as part of the
official SOHViewer docs, in docstrings, or even on the web in blog posts,
articles, and such.
Submit Feedback
~~~~~~~~~~~~~~~
The best way to send feedback is to file an issue at
https://git.passcal.nmt.edu/software_public/passoft/sohstationviewer/issues.
If you are proposing a feature:
* Explain in detail how it would work.
* Keep the scope as narrow as possible, to make it easier to implement.
* Remember that this is a volunteer-driven project, and that contributions
are welcome :)
Get Started!
------------
Ready to contribute? Here's how to set up `rt2ms` for local development.
1. Clone the `rt2ms` repo:
* $ git clone https://git.passcal.nmt.edu/software_public/passoft/sohstationviewer.git
2. Install your local copy:
* $ pip install -e .[dev]
3. Create a branch for local development:
* $ git checkout -b name-of-your-bugfix-or-feature
Now you can make your changes locally.
4. When you're done making changes, check that your changes pass the
tests:
* $ python -m unittest
5. Commit your changes and push your branch to GitHub:
* $ git add .
* $ git commit -m "Your detailed description of your changes."
* $ git push origin name-of-your-bugfix-or-feature
6. Submit a merge request through the Gitlab website.
Pull Request Guidelines
-----------------------
Before you submit a merge request, check that it meets these guidelines:
1. The merge request should include tests.
2. If the merge request adds functionality, the docs should be updated. Put
your new functionality into a function with a docstring, and add the
feature to the list in README.rst.
3. The pull request should work for Python 3.[9,10,11]
Deploying
---------
A reminder for the maintainers on how to deploy.
Make sure all your changes are committed.
Then run:
* $ git push
* $ git push --tags
......@@ -2,7 +2,12 @@
History
=======
2021.xxx
2023.1.0.0
--------
* First release
2023.1.0.1
--------
* Fixed a problem with SOHViewer not fitting on smaller resolutions
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Visualize State-of-Health packets from raw data recorded by different
type of dataloggers.
Copyright (C) 2018 IRIS PASSCAL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
include HISTORY.rst
include README.rst
include sohstationviewer/database/soh.db
graft sohstationviewer/documentation
graft sohstationviewer/images
recursive-exclude * __pycache__
recursive-exclude * sohstationviewer/__pycache__
recursive-exclude * *.py[co]
......@@ -8,43 +8,6 @@ Description
Visualize State-of-Health packets from raw data recorded by different type of dataloggers.
Directory Structure
-------------------
sohstationviewer/
model/
core/
view/
core/
ui/
controller/
core/
tests/
Directory Description
---------------------
**sohstationviewer/**
All codes for running sohstationviewer.
**sohstationviewer/model/**
Codes for reading data from raw files and setting data from config files.
**sohstationviewer/view/**
Codes for Graphical User Interface (GUI).
**sohstationviewer/view/ui/**
ui files from QtDesigner.
**sohstationviewer/controller/**
Codes for logical processes.
**tests/**
Unittest files for the codes. (GUI will not be tested)
License
-------
GNU General Public License v3 (GPLv3)
package:
name: sohviewer
version: 2023.1.0.1
source:
path: ../
build:
noarch: python
script: {{ PYTHON }} -m pip install . --no-deps -vv
requirements:
build:
- python >=3.9
- pip
run:
- python >=3.9
- numpy>=1.23.0
- obspy >=1.3.0
- PySide6>=6.5.2
- matplotlib>=3.5.0
test:
source_files:
- tests
- sohstationviewer/database/soh.db
commands:
- python -m unittest
about:
home: https://www.passcal.nmt.edu/content/software-resources
dev_url: https://git.passcal.nmt.edu/software_public/passoft/sohstationviewer
license: GPLv3
license_file: LICENSE
summary: Visualize State-of-Health packets from raw data recorded by different type of dataloggers.
## To read data from data card:
Different kinds of data card: SD card, CF card or flash drive
To read data from data card, check the checkbox "From Data Card".
File List box will display "Data Card" and the data in the selected card can be
read without selecting "Data Card" in the box.
<br />
<br />
<img alt="From Data Card checkbox" src="images/data_card/from_data_card_checkbox.png" height="80" />
<br />
Note: This will work the same way as selecting the current folder nested in
the first level of a data set.
### Baler data
Baler data has data/ folder for main data and sdata/ folder for backup
data. When Baler data is selected, the radio buttons for data/ and sdata/
are enable for user to select one of the folder to read from.
<br />
<br />
<img alt="data/sdata radio buttons" src="images/data_card/data_sdata_radio_buttons.png" height="80" />
<br />
### CF card
When CF card is selected, the serial numbers of the DASs in the CF card will
be listed for user to select for reading.
<br />
<br />
<img alt="DAS in CF Card" src="images/data_card/das_in_cf_card.png" height="100" />
<br />
Note: DASs list will be displayed in the File List box no matter the From Data
Card checkbox is checked or not.
\ No newline at end of file
documentation/images/data_card/data_sdata_radio_buttons.png

13.5 KiB

documentation/images/data_card/from_data_card_checkbox.png

10.9 KiB

documentation/images/save_plots/save_button_tps.png

31.1 KiB

documentation/images/tps/tps_color_range.png

17.9 KiB

......@@ -20,25 +20,28 @@ setup(
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
'Natural Language :: English',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
],
description="Visualize State-of-Health packets from raw data recorded by "
"different type of dataloggers.",
entry_points={
'console_scripts': [
'sohstationviewer=sohstationviewer.sohstationviewer:main',
'sohviewer=sohstationviewer.main:main',
],
},
install_requires=['obspy',
'PySide6',
'matplotlib',
'numpy'],
install_requires=[
'numpy>=1.23.0',
'obspy>=1.3.0',
'PySide6>=6.5.2',
'matplotlib>=3.5.0',
],
setup_requires=[],
extras_require={
'dev': [
'flake8'
'flake8',
'tox'
]
},
license="GNU General Public License v3",
......@@ -46,8 +49,8 @@ setup(
include_package_data=True,
keywords='sohstationviewer',
name='sohstationviewer',
packages=find_packages(include=['sohstationviewer']),
url='https://git.passcal.nmt.edu/passoft/sohstationviewer',
version='2021.167',
packages=find_packages(include=['sohstationviewer*']),
url='https://git.passcal.nmt.edu/software_public/passoft/sohstationviewer',
version='2023.1.0.1',
zip_safe=False,
)
#!/usr/bin/env python3
import platform
import os
import sys
import traceback
from PySide6 import QtWidgets
from PySide6.QtWidgets import QMessageBox, QErrorMessage
from sohstationviewer.view.main_window import MainWindow
from sohstationviewer.conf.config_processor import (
ConfigProcessor,
BadConfigError,
)
def main():
app = QtWidgets.QApplication(sys.argv)
wnd = MainWindow()
config = ConfigProcessor()
config.load_config()
need_reset = False
try:
config.validate_config()
config.apply_config(wnd)
except (BadConfigError, ValueError) as e:
bad_config_dialog = QMessageBox()
bad_config_dialog.setText('Something went wrong when reading the '
'config.')
bad_config_dialog.setDetailedText(traceback.format_exc())
bad_config_dialog.setInformativeText('Do you want to reset the config '
'file?')
bad_config_dialog.setStandardButtons(QMessageBox.Ok |
QMessageBox.Close)
bad_config_dialog.setDefaultButton(QMessageBox.Ok)
bad_config_dialog.setIcon(QMessageBox.Critical)
reset_choice = bad_config_dialog.exec_()
if reset_choice == QMessageBox.Ok:
need_reset = True
else:
sys.exit(1)
if need_reset:
try:
config.reset()
except OSError:
QMessageBox.critical(None, 'Cannot reset config',
'Config file cannot be reset. Please '
'ensure that it is not opened in another '
'program.',
QMessageBox.Close)
sys.exit(1)
config.apply_config(wnd)
wnd.show()
sys.exit(app.exec())
if __name__ == '__main__':
main()
......@@ -13,6 +13,7 @@ default_config = f'''
from_data_card = False
data = False
sdata = False
log = False
[ColorMode]
black = True
......@@ -48,6 +49,7 @@ to_date = {QtCore.QDate.currentDate().toString("yyyy-MM-dd")}
mp_color_mode = regular
tps_color_mode = High
date_mode = YYYY-MM-DD
add_mass_pos_to_soh = False
'''
......@@ -62,7 +64,7 @@ class ConfigProcessor:
def __init__(self):
self.config = configparser.ConfigParser()
self.expected_keys = {
'from_data_card', 'data', 'sdata',
'from_data_card', 'data', 'sdata', 'log',
'black', 'white',
'min_gap_length',
'mp123zne', 'mp456uvw',
......@@ -71,7 +73,8 @@ class ConfigProcessor:
'plot_tps', 'plot_raw',
'all_soh',
'from_date', 'to_date',
'mp_color_mode', 'tps_color_mode', 'date_mode'
'mp_color_mode', 'tps_color_mode', 'date_mode',
'add_mass_pos_to_soh' # noqa: E131
}
def load_config(self):
......@@ -79,7 +82,7 @@ class ConfigProcessor:
Load the config file if there is one, otherwise load the default
config.
"""
config_path = Path('sohstationviewer/conf/read_settings.ini')
config_path = Path('conf/read_settings.ini')
if not config_path.exists():
self.config.read_string(default_config)
else:
......@@ -109,10 +112,16 @@ class ConfigProcessor:
f'missing keys are: {", ".join(missing_keys)}'
)
from_data_card_checked = self.config.getboolean('FileRead',
'from_data_card')
data_checked = self.config.getboolean('FileRead', 'data')
sdata_checked = self.config.getboolean('FileRead', 'sdata')
log_checked = self.config.getboolean('FileRead', 'log')
if data_checked and sdata_checked:
raise BadConfigError('data and sdata cannot both be chosen.')
if from_data_card_checked and log_checked:
raise BadConfigError('Cannot read from data card and log file at '
'the same time.')
black_color_mode = self.config.getboolean('ColorMode', 'black')
white_color_mode = self.config.getboolean('ColorMode', 'white')
......@@ -187,6 +196,7 @@ class ConfigProcessor:
)
window.data_radio_button.setChecked(get_bool('FileRead', 'data'))
window.sdata_radio_button.setChecked(get_bool('FileRead', 'sdata'))
window.log_checkbox.setChecked(get_bool('FileRead', 'log'))
window.background_black_radio_button.setChecked(
get_bool('ColorMode', 'black')
......@@ -253,6 +263,10 @@ class ConfigProcessor:
elif date_mode == 'YYYY:DOY':
window.yyyy_doy_action.trigger()
window.add_masspos_to_rt130_soh.setChecked(
get_bool('MiscOptions', 'add_mass_pos_to_soh')
)
def reset(self):
self.config = configparser.ConfigParser()
self.config.read_string(default_config)
......
import sys
if sys.version_info.minor >= 8:
from typing import Literal
from typing import Literal
# The current version of SOHStationViewer
SOFTWARE_VERSION = '2023.1.0.1'
# waveform pattern
WF_1ST = 'A-HLM-V'
......@@ -11,7 +12,7 @@ WF_3RD = 'ZNE123456'
HIGHEST_INT = 1E100
# warn user if file bigger than this size
BIG_FILE_SIZE = 2 * 10**8
BIG_FILE_SIZE = 2 * 10**9 # 2 GB
# Matplotlib's performance be slow if data point total > than this limit
CHAN_SIZE_LIMIT = 10**6
......@@ -53,11 +54,12 @@ SEARCH_RESULTS = "Search Results.md"
ALL_COLOR_MODES = {'B': 'black', 'W': 'white'}
# The location of the config file
CONFIG_PATH = 'sohstationviewer/conf/read_settings.ini'
CONFIG_PATH = 'conf/read_settings.ini'
# List of image formats. Have to put PNG at the beginning to go with
# dpi in dialog
IMG_FORMAT = ['PNG', 'PDF', 'EPS', 'SVG']
# ================================================================= #
# PLOTTING CONSTANT
# ================================================================= #
......@@ -74,11 +76,10 @@ Z_ORDER = {'AXIS_SPINES': 0, 'CENTER_LINE': 1, 'LINE': 2, 'GAP': 3, 'DOT': 3}
# Distance from 'Hour' label to timestamp bar
HOUR_TO_TMBAR_D = 100
# day total limit for all tps channels to stay in one tab
DAY_LIMIT_FOR_TPS_IN_ONE_TAB = 180 # about half of a year
# ================================================================= #
# TYPING CONSTANT
# ================================================================= #
if sys.version_info.minor >= 8:
ColorMode = Literal['B', 'W']
else:
ColorMode = str
ColorMode = Literal['B', 'W']
import re
import os
from pathlib import Path
from sohstationviewer.conf.constants import (WF_1ST, WF_2ND, WF_3RD)
"""
......@@ -10,7 +12,7 @@ Third letter (Orientation Code): ZNE123
"""
dbConf = {
'dbpath': 'sohstationviewer/database/soh.db',
'dbpath': 'database/soh.db',
'seisRE': re.compile(f'[{WF_1ST}][{WF_2ND}][{WF_3RD}]'),
# key is last char of chan
'seisLabel': {'1': 'NS', '2': 'EW', 'N': 'NS', 'E': 'EW', 'Z': 'V'},
......@@ -42,3 +44,20 @@ dbConf = {
"If D is not defined, dots won't be displayed.\n"
"If L is not defined, lines will be plotted with color G")}
}
def modify_db_path():
"""
Modify dbpath to absolute path.
This function is called in case database needs to be used when the working
directory is a sub folder of root, sohstationviewer/. The following lines
need to be added:
from sohstationviewer.conf.dbSettings import modify_db_path
modify_db_path()
"""
global dbConf
current_file_path = os.path.abspath(__file__)
root = Path(current_file_path).parent.parent
db_path = [x for x in root.glob('**/soh.db')][0]
dbConf['dbpath'] = db_path.as_posix()
"""
Functions that process data for plotting
"""
import math
from typing import List, Union, Optional, Tuple, Dict
from obspy import UTCDateTime
from sohstationviewer.conf import constants as const
from sohstationviewer.view.util.enums import LogType
MAX_INT = 1E100
MAX_FLOAT = 1.0E100
# TODO: put this in DB
mass_pos_volt_ranges = {"regular": [0.5, 2.0, 4.0, 7.0],
"trillium": [0.5, 1.8, 2.4, 3.5]}
mass_pos_color_pallets = {"B": ["C", "G", "Y", "R", "M"],
"W": ["B", "B", "B", "B", "B"]}
def get_masspos_value_colors(
range_opt: str, chan_id: str, c_mode: str,
processing_log: List[Tuple[str, LogType]],
ret_type: str = 'str'
) -> Optional[Union[str, List[Tuple[float, str]]]]:
"""
Create a map between value and color based on given rangeOpt and c_mode to
display mass position plots.
:param range_opt: massPosVoltRangeOpt got from Options Menu - MP coloring
in Main Window to define different values for mass position.
(regular/trillium)
:param chan_id: ID of the channel
:param c_mode: color mode (B/W)
:param processing_log: list of processing info and type
:param ret_type: request return type
:return: [(value, color), (value, color) ...]
if retType is 'str', return "value:color|value:color"
"""
if range_opt.lower() not in mass_pos_volt_ranges.keys():
processing_log.append(
(
f"{chan_id}: The current selected Mass Position color range is"
f" '{range_opt}' isn't allowable. The accept ranges are: "
f"{', '.join(mass_pos_volt_ranges.keys())}",
LogType.ERROR
)
)
return
mass_pos_volt_range = mass_pos_volt_ranges[range_opt]
mass_pos_color_pallet = mass_pos_color_pallets[c_mode]
value_colors = []
for i in range(len(mass_pos_volt_range)):
if ret_type == 'str':
value_colors.append(
"%s:%s" % (mass_pos_volt_range[i], mass_pos_color_pallet[i]))
else:
value_colors.append(
(mass_pos_volt_range[i], mass_pos_color_pallet[i])
)
if i == len(mass_pos_volt_range) - 1:
if ret_type == 'str':
value_colors.append(
"%s:+%s" % (
mass_pos_volt_range[i], mass_pos_color_pallet[i + 1]))
else:
value_colors.append(
(mass_pos_volt_range[i], mass_pos_color_pallet[i + 1]))
if ret_type == 'str':
return '|'.join(value_colors)
return value_colors
def format_time(time: Union[UTCDateTime, float], date_mode: str,
time_mode: Optional[str] = None) -> str:
......