Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
L
locklost
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Deploy
Releases
Package Registry
Model registry
Operate
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Benjamin Mannix
locklost
Commits
643c5286
Commit
643c5286
authored
4 years ago
by
Jameson Rollins
Browse files
Options
Downloads
Plain Diff
Merge branch 'summary' into 'master'
See merge request
jameson.rollins/locklost!96
parents
9750f3d5
1b290495
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
locklost/summary.py
+132
-120
132 additions, 120 deletions
locklost/summary.py
with
132 additions
and
120 deletions
locklost/summary.py
+
132
−
120
View file @
643c5286
...
...
@@ -3,7 +3,10 @@ import argparse
import
numpy
as
np
import
matplotlib.pyplot
as
plt
from
collections
import
defaultdict
from
gpstime
import
gpsnow
,
gpstime
import
pytz
import
logging
from
.
import
config
from
.event
import
find_events
...
...
@@ -16,82 +19,107 @@ EPOCHS = {
'
week
'
:
int
(
gpsnow
())
-
7
*
24
*
3600
,
}
if
config
.
IFO
==
'
H1
'
:
local_tz
=
pytz
.
timezone
(
'
US/Pacific
'
)
if
config
.
IFO
==
'
L1
'
:
local_tz
=
pytz
.
timezone
(
'
US/Eastern
'
)
def
grab_data
(
gps
):
"""
Returns relevant lockloss summary data within three time ranges.
Looks through O3 lockloss data and returns counts for the locklosses
from each state, the duration in the final state, and the first saturated
suspension channel for the three most common locklosses. Does this for the
run, the last 30 days, and the last week.
Looks through O3 lockloss data and returns counts for the specificed check
functions. Does this for the run, the last 30 days, and the last week.
"""
shift_times
=
{
'
H1
'
:
[
np
.
arange
(
0
,
8
),
np
.
arange
(
8
,
16
),
np
.
arange
(
16
,
24
)],
'
L1
'
:
[
np
.
concatenate
(([
23
,
24
],
np
.
arange
(
22
,
8
))),
np
.
arange
(
8
,
12
),
np
.
arange
(
12
,
22
)]
}
shift_names
=
[
'
owl
'
,
'
day
'
,
'
eve
'
]
shifts
=
{
'
owl
'
:
{
'
time
'
:
np
.
arange
(
0
,
8
),
'
counts
'
:
0
,
},
'
day
'
:
{
'
time
'
:
np
.
arange
(
8
,
16
),
'
counts
'
:
0
,
},
'
eve
'
:
{
'
time
'
:
np
.
arange
(
16
,
24
),
'
counts
'
:
0
,
},
shift_names
[
x
]:
{
'
time
'
:
shift_times
[
config
.
IFO
][
x
],
'
counts
'
:
0
}
for
x
in
range
(
3
)
}
transitions
=
[]
transitions
=
defaultdict
(
int
)
observe_durations
=
[]
saturations
=
{
'
als
'
:
[],
'
darm
'
:
[],
'
observe
'
:
[],
'
H1
'
:
{
'
LOCKING_ALS
'
:
defaultdict
(
int
),
'
ACQUIRE_DRM1_1F
'
:
defaultdict
(
int
),
'
Observe
'
:
defaultdict
(
int
),
},
'
L1
'
:
{
'
Observe
'
:
defaultdict
(
int
)
},
}
five_sats
=
[]
tags
=
{
'
MAINTENANCE
'
:
0
,
'
ADS_EXCURSION
'
:
0
,
'
BOARD_SAT
'
:
0
,
'
BRS_GLITCH
'
:
0
,
'
SEISMIC
'
:
0
,
'
WINDY
'
:
0
,
'
Unknown
'
:
0
}
for
i
,
event
in
enumerate
(
find_events
(
after
=
gps
,
state
=
'
0-600
'
)):
transitions
.
append
(
event
.
transition_index
[
0
])
tag_count
=
defaultdict
(
int
)
tags
=
[
'
MAINTENANCE
'
,
'
ADS_EXCURSION
'
,
'
BOARD_SAT
'
,
'
BRS_GLITCH
'
,
'
EARTHQUAKE
'
,
'
MICROSEISMIC
'
,
'
ANTHROPOGENIC
'
,
'
WINDY
'
,
'
Unknown
'
,
]
event_count
=
0
for
event
in
find_events
(
after
=
gps
,
state
=
'
0-{}
'
.
format
(
config
.
GRD_NOMINAL_STATE
[
0
])):
transitions
[
event
.
transition_index
[
0
]]
+=
1
# check event/append to relevant lists
observe_durations
=
check_durations
(
event
,
observe_durations
)
saturations
,
five_sats
=
check_saturations
(
event
,
saturations
,
five_sats
)
shifts
=
check_shift
(
event
,
shifts
)
tags
=
check_tags
(
event
,
tags
)
tag_count
=
check_tags
(
event
,
tags
,
tag_count
)
event_count
+=
1
return
transitions
,
observe_durations
,
saturations
,
five_sats
,
shifts
,
tags
logging
.
info
(
"
Events analyzed: {}
"
.
format
(
event_count
))
return
transitions
,
observe_durations
,
saturations
,
five_sats
,
shifts
,
tag_count
def
check_tags
(
event
,
tags
):
ref_sum
=
sum
(
tags
.
values
())
for
tag_key
in
tags
:
if
event
.
has_tag
(
tag_key
):
tags
[
tag_key
]
+=
1
def
check_tags
(
event
,
tags
,
tag_count
):
"""
Checks event for most relevant tag to the lockloss.
Checks event for tags, then increments the and returns the
'
tag_count
'
dictionary just once based on tag priority. Priority is given by the
'
tags
'
list.
"""
for
tag
in
tags
:
if
event
.
has_tag
(
tag
):
tag_count
[
tag
]
+=
1
break
if
sum
(
tags
.
values
())
==
ref_sum
:
tags
[
'
Unknown
'
]
+=
1
return
tags
else
:
tag_count
[
'
Unknown
'
]
+=
1
return
tag_count
def
check_shift
(
event
,
shifts
):
"""
Checks which operating shift event happened during.
Checks which operator shift the lockloss gps happened during and increments
a counter for that shift (for locklosses from Observe).
"""
if
not
event
.
has_tag
(
'
OBSERVE
'
):
return
shifts
gt
=
gpstime
.
fromgps
(
event
.
gps
)
if
even
t
.
h
as
_tag
(
'
OBSERVE
'
):
for
key
in
shifts
.
keys
()
:
if
gt
.
hour
in
shifts
[
key
][
'
time
'
]:
shifts
[
key
][
'
counts
'
]
+=
1
break
gt
=
g
t
.
as
timezone
(
local_tz
)
for
key
in
shifts
:
if
gt
.
hour
in
shifts
[
key
][
'
time
'
]:
shifts
[
key
][
'
counts
'
]
+=
1
break
return
shifts
def
check_durations
(
event
,
durations
):
"""
Check if lockloss was from Observe and log lock duration.
"""
"""
Check
s
if lockloss was from Observe and log
s
lock duration.
"""
if
event
.
has_tag
(
'
OBSERVE
'
):
previous
=
event
.
previous_state
if
previous
:
...
...
@@ -100,28 +128,41 @@ def check_durations(event, durations):
def
check_saturations
(
event
,
saturations
,
five_sats
):
"""
Checks for first five saturating suspensions around time of lockloss.
Checks if lockloss is from one of the top three lockloss states, then
logs which five suspensions saturated first into five_sats.
"""
sat_path
=
event
.
path
(
'
saturations.csv
'
)
sat_conditions
=
{
'
H1
'
:
{
'
Observe
'
:
event
.
has_tag
(
'
OBSERVE
'
),
'
ACQUIRE_DRM1_1F
'
:
event
.
transition_index
[
0
]
==
101
,
'
LOCKING_ALS
'
:
event
.
transition_index
[
0
]
==
15
,
},
'
L1
'
:
{
'
Observe
'
:
event
.
has_tag
(
'
OBSERVE
'
),
},
}
if
os
.
path
.
exists
(
sat_path
):
sats
=
get_five_sats
(
sat_path
)
five_sats
.
append
(
sats
)
sat_conditions
=
{
'
observe
'
:
event
.
has_tag
(
'
OBSERVE
'
),
'
darm
'
:
event
.
transition_index
[
0
]
==
101
,
'
als
'
:
event
.
transition_index
[
0
]
==
15
,
}
for
key
,
condition
in
sat_conditions
.
items
():
for
key
,
condition
in
sat_conditions
[
config
.
IFO
].
items
():
if
condition
:
if
os
.
path
.
exists
(
sat_path
):
saturations
[
key
].
append
(
sats
[
0
]
)
saturations
[
config
.
IFO
][
key
][
sats
[
0
]
]
+=
1
else
:
saturations
[
key
].
append
(
'
No saturations
'
)
saturations
[
config
.
IFO
][
key
][
'
No saturations
'
]
+=
1
return
saturations
,
five_sats
def
get_five_sats
(
sat_path
):
"""
Returns shortened names of first
(up to) five saturating suspension channels
.
"""
Returns shortened names of first
five channels located at sat_path
.
Returns list containing up to the first five saturations in a given
lockloss. Locklosses with no saturations will not be called due to logic
in check_saturations.
"""
all_sats
=
np
.
genfromtxt
(
sat_path
,
...
...
@@ -131,8 +172,7 @@ def get_five_sats(sat_path):
)
five_sats
=
np
.
array
([])
all_sats
=
np
.
array
(
all_sats
,
ndmin
=
1
)
sat_lim
=
min
([
all_sats
.
size
,
5
])
for
sat
in
all_sats
[:
sat_lim
]:
for
sat
in
all_sats
:
# create shortened channel name (excluding IFO, quadrant, characters)
sat_123
=
sat
.
split
(
'
-
'
)
sat1
=
sat_123
[
0
]
...
...
@@ -142,6 +182,8 @@ def get_five_sats(sat_path):
# Make sure the degenerate channels don't get added
if
channel_shorthand
not
in
five_sats
:
five_sats
=
np
.
append
(
five_sats
,
channel_shorthand
)
if
len
(
five_sats
)
==
5
:
break
return
five_sats
...
...
@@ -152,7 +194,6 @@ def plot_summary(path, epoch):
Plots histograms for lockloss state transitions, time lengths in Observing,
and first saturating suspension channel for the three most common lockloss
states. Saves these to the example_plots directory.
"""
epoch_path
=
os
.
path
.
join
(
path
,
epoch
)
try
:
...
...
@@ -160,39 +201,19 @@ def plot_summary(path, epoch):
except
FileExistsError
:
pass
transitions
,
observe_durations
,
saturations
,
five_sats
,
shifts
,
tags
=
grab_data
(
EPOCHS
[
epoch
])
state_occurence
=
np
.
array
([])
sat_occurence
=
{
'
als
'
:
[],
'
darm
'
:
[],
'
observe
'
:
[]}
sat_names
=
{
'
observe
'
:
'
Observe
'
,
'
darm
'
:
'
ACQUIRE_DRM1_1F
'
,
'
als
'
:
'
LOCKING_ALS
'
}
sat_positions
=
{
'
als
'
:
0
,
'
darm
'
:
0
,
'
observe
'
:
0
}
# Collecting str values for the histogram x-axis and counting number
# of values in each 'bin'
# Transition state bin structuring
states
=
set
(
transitions
)
for
state
in
states
:
state_occurence
=
np
.
append
(
state_occurence
,
transitions
.
count
(
state
))
state_bar
=
sorted
(
zip
(
states
,
state_occurence
))
# sorting states numerically
states
,
state_occurence
=
zip
(
*
state_bar
)
state_position
=
np
.
arange
(
len
(
states
))
# for histogram later
str_states
=
[
str
(
i
)
for
i
in
states
]
# for histogram later
# Saturating suspension channel bin structuring
sat_sets
=
{
key
:
set
(
val
)
for
key
,
val
in
saturations
.
items
()}
for
key
,
sat_set
in
sat_sets
.
items
():
for
channel
in
sat_set
:
sat_occurence
[
key
]
=
np
.
append
(
sat_occurence
[
key
],
saturations
[
key
].
count
(
channel
))
sat_bar
=
sorted
(
zip
(
sat_set
,
sat_occurence
[
key
]))
sat_sets
[
key
],
sat_occurence
[
key
]
=
zip
(
*
sat_bar
)
sat_positions
[
key
]
=
np
.
arange
(
len
(
sat_set
))
transitions
,
observe_durations
,
saturations
,
five_sats
,
shifts
,
tag_count
=
grab_data
(
EPOCHS
[
epoch
])
plotutils
.
set_rcparams
()
# Transition state plot
fig
,
ax
=
plt
.
subplots
(
1
,
figsize
=
(
22
,
16
))
state_position
=
np
.
arange
(
len
(
transitions
))
sort_keys
=
list
(
transitions
.
keys
())
sort_keys
.
sort
()
sort_values
=
[
transitions
[
x
]
for
x
in
sort_keys
if
bool
(
sort_keys
)]
fig
,
ax
=
plt
.
subplots
(
1
,
figsize
=
(
22
,
16
))
ax
.
bar
(
state_position
,
s
tate_occurence
,
s
ort_values
,
align
=
'
center
'
,
)
ax
.
set_xlabel
(
'
State from which lockloss has occurred
'
,
labelpad
=
10
)
...
...
@@ -200,13 +221,12 @@ def plot_summary(path, epoch):
ax
.
set_title
(
'
O3 lockloss occurences by final state: %s
'
%
(
epoch
))
ax
.
set_xticks
(
state_position
)
ax
.
tick_params
(
axis
=
'
x
'
,
which
=
'
major
'
,
labelsize
=
18
)
ax
.
set_xticklabels
(
s
tr_state
s
,
rotation
=
45
,
ha
=
'
right
'
)
ax
.
set_xticklabels
(
s
ort_key
s
,
rotation
=
45
,
ha
=
'
right
'
)
ax
.
set_xlim
([
-
1
,
state_position
.
size
])
plt
.
gcf
().
text
(
0.02
,
0.02
,
"
Created: {}
"
.
format
(
gpsnow
()),
fontsize
=
16
)
fig
.
tight_layout
()
plot_name
=
'
Lockloss_states
'
outpath_plot
=
os
.
path
.
join
(
epoch_path
,
plot_name
)
outpath_plot
=
os
.
path
.
join
(
epoch_path
,
'
Lockloss_states
'
)
fig
.
savefig
(
outpath_plot
,
bbox_inches
=
'
tight
'
)
plt
.
close
()
...
...
@@ -230,29 +250,32 @@ def plot_summary(path, epoch):
plt
.
gcf
().
text
(
0.02
,
0.02
,
"
Created: {}
"
.
format
(
gpsnow
()),
fontsize
=
16
)
fig
.
tight_layout
()
plot_name
=
'
Lock_durations
'
outpath_plot
=
os
.
path
.
join
(
epoch_path
,
plot_name
)
outpath_plot
=
os
.
path
.
join
(
epoch_path
,
'
Lock_durations
'
)
fig
.
savefig
(
outpath_plot
,
bbox_inches
=
'
tight
'
)
plt
.
close
()
# Saturating suspension channel plot
for
key
,
occurence
in
sat_occurence
.
items
():
fig
,
ax
=
plt
.
subplots
(
1
,
figsize
=
(
22
,
16
))
for
state
,
sat_dict
in
saturations
[
config
.
IFO
].
items
():
sat_position
=
np
.
arange
(
len
(
sat_dict
))
sort_keys
=
list
(
sat_dict
.
keys
())
sort_keys
.
sort
()
sort_values
=
[
sat_dict
[
x
]
for
x
in
sort_keys
if
bool
(
sort_keys
)]
fig
,
ax
=
plt
.
subplots
(
1
,
figsize
=
(
22
,
16
))
ax
.
bar
(
sat_position
s
[
key
]
,
occurence
,
sat_position
,
sort_values
,
align
=
'
center
'
,
)
ax
.
set_xlabel
(
'
First suspension to saturate before lockloss
'
,
labelpad
=
10
)
ax
.
set_ylabel
(
'
Number of locklosses
'
)
ax
.
set_title
(
'
%s locklosses by saturating suspension: %s
'
%
(
s
at_names
[
key
]
,
epoch
))
ax
.
set_xticks
(
sat_position
s
[
key
]
)
ax
.
set_xticklabels
(
s
at_sets
[
key
]
,
rotation
=
45
,
ha
=
'
right
'
)
ax
.
set_xlim
([
-
1
,
sat_position
s
[
key
]
.
size
])
ax
.
set_title
(
'
%s locklosses by saturating suspension: %s
'
%
(
s
tate
,
epoch
))
ax
.
set_xticks
(
sat_position
)
ax
.
set_xticklabels
(
s
ort_
key
s
,
rotation
=
45
,
ha
=
'
right
'
)
ax
.
set_xlim
([
-
1
,
sat_position
.
size
])
plt
.
gcf
().
text
(
0.02
,
0.02
,
"
Created: {}
"
.
format
(
gpsnow
()),
fontsize
=
16
)
fig
.
tight_layout
()
plot_name
=
'
%s_lockloss_saturations
'
%
(
s
at_names
[
key
]
)
plot_name
=
'
%s_lockloss_saturations
'
%
(
s
tate
)
outpath_plot
=
os
.
path
.
join
(
epoch_path
,
plot_name
)
fig
.
savefig
(
outpath_plot
,
bbox_inches
=
'
tight
'
)
plt
.
close
()
...
...
@@ -276,37 +299,28 @@ def plot_summary(path, epoch):
plt
.
gcf
().
text
(
0.02
,
0.02
,
"
Created: {}
"
.
format
(
gpsnow
()),
fontsize
=
16
)
fig
.
tight_layout
()
plot_name
=
'
lockloss_by_shift
'
outpath_plot
=
os
.
path
.
join
(
epoch_path
,
plot_name
)
outpath_plot
=
os
.
path
.
join
(
epoch_path
,
'
Lockloss_by_shift
'
)
fig
.
savefig
(
outpath_plot
,
bbox_inches
=
'
tight
'
)
plt
.
close
()
# Associated tag plot
temp_dict
=
dict
(
tags
)
for
key
,
value
in
tags
.
items
():
if
value
==
0
:
del
temp_dict
[
key
]
tags
=
temp_dict
ts
=
tags
.
keys
()
counts
=
tags
.
values
()
fig
,
ax
=
plt
.
subplots
(
1
,
figsize
=
(
22
,
16
))
shift_x
=
np
.
arange
(
0
,
len
(
tags
))
fig
,
ax
=
plt
.
subplots
(
1
,
figsize
=
(
22
,
16
))
shift_x
=
np
.
arange
(
0
,
len
(
tag_count
))
ax
.
bar
(
shift_x
,
count
s
,
tag_
count
.
values
()
,
align
=
'
center
'
,
)
ax
.
set_xlabel
(
'
Lockloss tags
'
,
labelpad
=
10
)
ax
.
set_ylabel
(
'
Number of locklosses
'
)
ax
.
set_title
(
'
Number of locklosses with given tag: %s
'
%
(
epoch
))
ax
.
set_xticks
(
shift_x
)
ax
.
set_xticklabels
(
t
s
,
rotation
=
45
,
ha
=
'
right
'
)
ax
.
set_xticklabels
(
t
ag_count
.
keys
()
,
rotation
=
45
,
ha
=
'
right
'
)
ax
.
set_xlim
([
-
1
,
shift_x
.
size
])
plt
.
gcf
().
text
(
0.02
,
0.02
,
"
Created: {}
"
.
format
(
gpsnow
()),
fontsize
=
16
)
fig
.
tight_layout
()
plot_name
=
'
lockloss_by_tag
'
outpath_plot
=
os
.
path
.
join
(
epoch_path
,
plot_name
)
outpath_plot
=
os
.
path
.
join
(
epoch_path
,
'
Lockloss_by_tag
'
)
fig
.
savefig
(
outpath_plot
,
bbox_inches
=
'
tight
'
)
plt
.
close
()
...
...
@@ -319,9 +333,7 @@ def _parser_add_arguments(parser):
def
main
(
args
=
None
):
"""
Generate lockloss summary plots
"""
"""
Generate lockloss summary plots.
"""
if
not
args
:
parser
=
argparse
.
ArgumentParser
()
_parser_add_arguments
(
parser
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment