Skip to content

Commit 0631f25

Browse files
authored
Merge pull request #5 from EarthScope/dq-45-update-dependencies
DQ 45 Update Dependency Versions
2 parents 0b0379f + 1bf6dc4 commit 0631f25

12 files changed

+2215
-1629
lines changed

CHANGELOG.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
Version 1.2.0
2+
- Updated to use python 3.12
3+
- Updated dependency versions, requiring the retirement of deprecated methods used internally.
4+
- Converted remaining references of "IRIS" to "EarthScope". Use of "IRIS" in the preference file will continue to work, but suggest updating to "EarthScope"
5+
16
Version 1.1.1
27
- Update to use python 3.6.15
38

QuARG.py

Lines changed: 279 additions & 306 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# QuARG
22

3-
#### Questions or comments can be directed to the EarthScope (formerly IRIS) Quality Assurance Group at <a href="mailto:data-help@earthscope.org">data-help@earthscope.org</a>.
3+
#### Questions or comments can be directed to the EarthScope (formerly IRIS) Quality Assurance Group at <a href="mailto:help@earthscope.org">help@earthscope.org</a>.
44
For detailed documentation, check out [EarthScope.github.io/quarg/](https://EarthScope.github.io/quarg/DOCUMENTATION.html)
55
<br />
66

7-
**QuARG**, the Quality Assurance Report Generator, is a Python client that allows network operators to generate quality assurance (QA) reports from start to finish. These reports utilize EarthScope’s database of [MUSTANG](http://service.iris.edu/mustang/) data quality metrics to find and highlight potential issues in the data, reducing the amount of time that analysts need to spend scanning the data for problems.
7+
**QuARG**, the Quality Assurance Report Generator, is a Python client that allows network operators to generate quality assurance (QA) reports from start to finish. These reports utilize EarthScope’s database of [MUSTANG](https://service.earthscope.org/mustang/) data quality metrics to find and highlight potential issues in the data, reducing the amount of time that analysts need to spend scanning the data for problems.
88

99
Over the years that IRIS produced Quality Assurance Reports, we refined the process of generating a report into four primary steps:
1010

@@ -21,7 +21,7 @@ Users have the ability to customize QuARG to adapt to their particular network.
2121
* Add, edit, or remove Thresholds based on what best fits the network instrumentation.
2222
* Group instrumentation by Network, Station, Locations, or Channels, defining thresholds individually for each group.
2323
* Use metric values sourced from either EarthScope or a local ISPAQ database. Similarly, locally-sourced or EarthScope-provided metadata.
24-
* Create preference files to minimize the number of fields that users need to input, easily track what thresholds were used to find issues, and potentially create a series of files to be utilized for different use-cases within a network. An example file preference_file_IRIS.py is provided in the base quarg directory.
24+
* Create preference files to minimize the number of fields that users need to input, easily track what thresholds were used to find issues, and potentially create a series of files to be utilized for different use-cases within a network. An example file preference_file_EarthScope.py is provided in the base quarg directory.
2525
* Use the built-in ticketing system or an external one, whichever works better for your workflow.
2626

2727
This utility guides users through the process of generating a list of potential issues, examining and tracking issues, and generating a report.
@@ -97,16 +97,18 @@ Instructions for Linux or macOS (Intel chip)
9797
```
9898
cd quarg
9999
conda update conda
100-
conda create --name quarg -c conda-forge --file quarg-conda-install.txt
100+
conda create --name quarg -c conda-forge python=3.12
101101
conda activate quarg
102+
conda install -c conda-forge --file quarg-conda-install.txt
102103
```
103104

104-
Instructions for macOS (Apple M1 or M2 chip):
105+
Instructions for macOS (Apple M-series chips, e.g., M1 - M5):
105106
```
106107
cd quarg
107108
conda update conda
108-
CONDA_SUBDIR=osx-64 conda create --name quarg -c conda-forge --file quarg-conda-install.txt
109+
CONDA_SUBDIR=osx-64 conda create --name quarg -c conda-forge python=3.12
109110
conda activate quarg
111+
CONDA_SUBDIR=osx-64 conda install -c conda-forge --file quarg-conda-install.txt
110112
```
111113

112114
See what is installed in our (quarg) environment with:

docs/DOCUMENTATION.html

Lines changed: 33 additions & 35 deletions
Large diffs are not rendered by default.

findIssues.py

Lines changed: 128 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -27,42 +27,78 @@
2727
import pandas as pd
2828

2929

30-
3130
# TODO: If ts_ metrics are used, must propagate through into the thresholds file
3231

3332
# ============================#
3433
# LOAD INPUT ARGUMENTS
35-
network = ''; station = ''; location = ''; channels = ''; start = '';end = ''; outfile = ''
34+
network = ""
35+
station = ""
36+
location = ""
37+
channels = ""
38+
start = ""
39+
end = ""
40+
outfile = ""
3641

3742
args = reportUtils.getArgs()
38-
start= args.start
43+
start = args.start
3944
end = args.end
4045
# month = args.month
4146

4247
preferenceFile = args.preference_file
4348

4449
if not preferenceFile:
4550
# If no preference file included, run everything
46-
thresholdGroups = ['Completeness','Amplitudes','Timing','State of Health','Metadata']
47-
groupsDict = {'Completeness':['avgGaps','gapsRatioGt12','noData'],
48-
'Amplitudes' : ['flat','lowRms','hiAmp','lowAmp','badResp',
49-
'avgSpikes','pegged','dead','noise1','noise2',
50-
'medianUnique','rmsRatio','xTalk',
51-
'gainRatio','nonCoher','polarity',
52-
'dcOffsets','nSpikes','rmsRatio'],
53-
'Timing' : ['poorTQual','suspectTime','noTime'],
54-
'State of Health' : ['ampSat','filtChg','clip',
55-
'spikes','glitch','padding','tSync'],
56-
'Metadata' : ['zDip','horDip','zeroZ','lowScale','nonMSUnits']}
57-
51+
thresholdGroups = [
52+
"Completeness",
53+
"Amplitudes",
54+
"Timing",
55+
"State of Health",
56+
"Metadata",
57+
]
58+
groupsDict = {
59+
"Completeness": ["avgGaps", "gapsRatioGt12", "noData"],
60+
"Amplitudes": [
61+
"flat",
62+
"lowRms",
63+
"hiAmp",
64+
"lowAmp",
65+
"badResp",
66+
"avgSpikes",
67+
"pegged",
68+
"dead",
69+
"noise1",
70+
"noise2",
71+
"medianUnique",
72+
"rmsRatio",
73+
"xTalk",
74+
"gainRatio",
75+
"nonCoher",
76+
"polarity",
77+
"dcOffsets",
78+
"nSpikes",
79+
"rmsRatio",
80+
],
81+
"Timing": ["poorTQual", "suspectTime", "noTime"],
82+
"State of Health": [
83+
"ampSat",
84+
"filtChg",
85+
"clip",
86+
"spikes",
87+
"glitch",
88+
"padding",
89+
"tSync",
90+
],
91+
"Metadata": ["zDip", "horDip", "zeroZ", "lowScale", "nonMSUnits"],
92+
}
93+
5894
else:
5995
try:
6096
with open(preferenceFile) as f:
6197
exec(compile(f.read(), preferenceFile, "exec"))
6298
except OSError:
63-
print('Cannot open', preferenceFile)
99+
print("Cannot open", preferenceFile)
64100
quit()
65-
101+
66102
# Commandline arguments override preference file values, if provided
67103
if args.network:
68104
network = args.network
@@ -71,7 +107,7 @@
71107
if args.locations:
72108
location = args.locations
73109
if args.channels:
74-
channels= args.channels
110+
channels = args.channels
75111
if args.outfile:
76112
outfile = args.outfile
77113
if args.metricsource:
@@ -88,6 +124,11 @@
88124
print("WARNING: No threshold file provided. Exiting.")
89125
quit()
90126

127+
# Allow for backward compatibility in preference file
128+
if metricSource == "IRIS":
129+
metricSource = "EarthScope"
130+
if metadataSource == "IRIS":
131+
metadataSource = "EarthScope"
91132

92133
directory = os.path.dirname(outfile)
93134

@@ -102,53 +143,64 @@
102143

103144
if os.path.isfile(outfile):
104145
resp1 = input("This file already exists - overwrite?[y/n]: ")
105-
if (resp1.upper() == 'Y') or (resp1.upper() == 'YES'):
106-
print('Removing existing file')
146+
if (resp1.upper() == "Y") or (resp1.upper() == "YES"):
147+
print("Removing existing file")
107148
os.remove(outfile)
108-
109-
elif (resp1.upper() == 'N') or (resp1.upper()== 'NO'):
110-
resp2= input('Should I append to the existing file?[y/n]: ')
111-
if (not resp2.upper() == 'Y') and (not resp2.upper() == 'YES'):
149+
150+
elif (resp1.upper() == "N") or (resp1.upper() == "NO"):
151+
resp2 = input("Should I append to the existing file?[y/n]: ")
152+
if (not resp2.upper() == "Y") and (not resp2.upper() == "YES"):
112153
quit("Exiting")
113154
else:
114-
print('Input not recognized, cancelling')
155+
print("Input not recognized, cancelling")
115156
quit()
116-
157+
117158
# Load up list of metrics and metadata, for reference later on
118159
if os.path.isfile(metrics_file):
119-
with open(metrics_file,'r') as f:
160+
with open(metrics_file, "r") as f:
120161
metricsList = f.read().splitlines()
121162
else:
122163
# This should not happen unless running outside of QuARG since QuARG.py has a check before running findIssues.py
123-
print("WARNING: Could not find list of MUSTANG metrics in file %s - does it exist?" % metrics_file)
124-
print(" You can create this list by entering the Thresholds Editor - it will automatically generate there")
164+
print(
165+
"WARNING: Could not find list of MUSTANG metrics in file %s - does it exist?"
166+
% metrics_file
167+
)
168+
print(
169+
" You can create this list by entering the Thresholds Editor - it will automatically generate there"
170+
)
125171
quit()
126-
172+
127173
if os.path.isfile(metadata_file):
128-
with open(metadata_file,'r') as f:
174+
with open(metadata_file, "r") as f:
129175
metadataList = f.read().splitlines()
130176
else:
131177
# This should not happen unless running outside of QuARG since QuARG.py has a check before running findIssues.py
132-
print("WARNING: Could not find list of IRIS metadata fields in file %s - does it exist?" % metadata_file)
133-
print(" You can create this list by entering the Thresholds Editor - it will automatically generate there")
178+
print(
179+
"WARNING: Could not find list of EarthScope metadata fields in file %s - does it exist?"
180+
% metadata_file
181+
)
182+
print(
183+
" You can create this list by entering the Thresholds Editor - it will automatically generate there"
184+
)
134185
quit()
135-
186+
136187

137188
# ============================#
138189
# GO THROUGH THRESHOLDS
139190

140191
# Add the header to the file
141-
with open(outfile, 'w') as f:
192+
with open(outfile, "w") as f:
142193
f.write("# Threshold|Target|Start|End|Ndays|Status|Value|Notes\n")
143-
f.close()
194+
f.close()
144195

145196
# Get metadata dataframe at the beginning to use wherever necessary, since it is always the same
146-
metadataDF = reportUtils.getMetadata(network, station, location, channels, start, end, metadataSource)
197+
metadataDF = reportUtils.getMetadata(
198+
network, station, location, channels, start, end, metadataSource
199+
)
147200

148201

149202
failedMetricsAll = list()
150203
failedThresholdsAll = list()
151-
# thresholdFile = './groupsTEST.txt'
152204
for thresholdGroup in thresholdGroups:
153205
print()
154206
print("Running %s Thresholds" % thresholdGroup)
@@ -157,46 +209,65 @@
157209
except:
158210
print(" Could not find any thresholds for %s" % thresholdGroup)
159211
continue
160-
212+
161213
thresholdsList.sort()
162-
163-
allMetrics, failedThresholds = thresholds.get_threshold_metrics(thresholdsList, thresholdFile)
214+
215+
allMetrics, failedThresholds = thresholds.get_threshold_metrics(
216+
thresholdsList, thresholdFile
217+
)
164218
metadatas = [e for e in metadataList if e in allMetrics]
165219
metrics = [e for e in metricsList if e in allMetrics]
166220

167-
# hasMetadata = False;
168221
hasMetrics = False
169-
# if len(metadatas) > 0:
170-
# print("This thresholds Group contains some metadata fields")
171-
# hasMetadata = True
172222
if len(metrics) > 0:
173223
hasMetrics = True
174224

175-
176225
if hasMetrics:
177-
metricDF, failedMetrics = reportUtils.mergeMetricDF(network, station, location, channels, start, end, metrics, metricSource)
226+
metricDF, failedMetrics = reportUtils.mergeMetricDF(
227+
network, station, location, channels, start, end, metrics, metricSource
228+
)
178229
else:
179-
metricDF = pd.DataFrame(columns=['value','target','start','end','network','station','location','channel'])
230+
metricDF = pd.DataFrame(
231+
columns=[
232+
"value",
233+
"target",
234+
"start",
235+
"end",
236+
"network",
237+
"station",
238+
"location",
239+
"channel",
240+
]
241+
)
180242
failedMetrics = list()
181-
243+
182244
for failedThreshold in failedThresholds:
183245
if not failedThreshold in failedThresholdsAll:
184246
failedThresholdsAll.append(failedThreshold)
185-
247+
186248
for failedMetric in failedMetrics:
187249
if not failedMetric in failedMetricsAll:
188250
failedMetricsAll.append(failedMetric)
189-
190-
# if hasMetrics == True and not metricDF.empty:
251+
191252
for threshold in thresholdsList:
192253
if not threshold in failedThresholds:
193-
thresholds.do_threshold(threshold, thresholdFile, metricDF, metadataDF, outfile, instruments, start, end, hasMetrics, chanTypes)
254+
thresholds.do_threshold(
255+
threshold,
256+
thresholdFile,
257+
metricDF,
258+
metadataDF,
259+
outfile,
260+
instruments,
261+
start,
262+
end,
263+
hasMetrics,
264+
chanTypes,
265+
)
194266

195-
with open('failedMetrics.txt','w') as f:
267+
with open("failedMetrics.txt", "w") as f:
196268
for failedThreshold in failedThresholdsAll:
197-
f.write('threshold: %s\n' % failedThreshold)
269+
f.write("threshold: %s\n" % failedThreshold)
198270
for failedMetric in failedMetricsAll:
199-
f.write('metric: %s\n' % failedMetric)
271+
f.write("metric: %s\n" % failedMetric)
200272

201273
print("INFO: Completed generating issue file")
202-

0 commit comments

Comments
 (0)