Compare commits
No commits in common. "84d3b98a1a1e0fd61dbcf29a0ab42853cefbc022" and "555aaaff318d8360f0fc2e09f69418a55fb95f3a" have entirely different histories.
84d3b98a1a
...
555aaaff31
30 changed files with 371 additions and 347 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,2 +0,0 @@
|
|||
__pycache__
|
||||
.pid*
|
||||
|
|
@ -4,11 +4,7 @@ RAD Webserver
|
|||
A web service to view quicklook plots of MSL RAD data. Built using [Bokeh](https://bokeh.org/) and the
|
||||
[RAD Loader](https://gitlab.physik.uni-kiel.de/mslrad/flight_tools).
|
||||
|
||||
The current version of the app is running at https://solar-orbiter.physik.uni-kiel.de/rad/plotter/.
|
||||
|
||||
The dose rate [mGy/day] in the B and E detectors are per day (i.e., 24 hours), not Sol.
|
||||
|
||||
The absorbed dose in the silicon B detector is not subtracted by the background contribution by the rover’s radioisotope thermoelectric generator (RTG) because it changes during the time.
|
||||
The current version of the app is running at https://solar-orbiter.physik.uni-kiel.de/mslrad/plotter.
|
||||
|
||||
How to set up
|
||||
-------------
|
||||
|
|
|
|||
BIN
backend/__pycache__/__init__.cpython-37.pyc
Normal file
BIN
backend/__pycache__/__init__.cpython-37.pyc
Normal file
Binary file not shown.
BIN
backend/__pycache__/bokeh_utils.cpython-37.pyc
Normal file
BIN
backend/__pycache__/bokeh_utils.cpython-37.pyc
Normal file
Binary file not shown.
BIN
backend/__pycache__/debounce.cpython-37.pyc
Normal file
BIN
backend/__pycache__/debounce.cpython-37.pyc
Normal file
Binary file not shown.
BIN
backend/__pycache__/plot.cpython-37.pyc
Normal file
BIN
backend/__pycache__/plot.cpython-37.pyc
Normal file
Binary file not shown.
BIN
backend/__pycache__/plot_utils.cpython-37.pyc
Normal file
BIN
backend/__pycache__/plot_utils.cpython-37.pyc
Normal file
Binary file not shown.
BIN
backend/__pycache__/plotcollection.cpython-37.pyc
Normal file
BIN
backend/__pycache__/plotcollection.cpython-37.pyc
Normal file
Binary file not shown.
BIN
backend/__pycache__/selector.cpython-37.pyc
Normal file
BIN
backend/__pycache__/selector.cpython-37.pyc
Normal file
Binary file not shown.
|
|
@ -134,9 +134,8 @@ class PlotCollection(ABC):
|
|||
self._native = True
|
||||
return df
|
||||
else:
|
||||
self._native = True
|
||||
return df
|
||||
#return df.resample(f'{self._tres}S').mean()
|
||||
self._native = False
|
||||
return df.resample(f'{self._tres}S').mean()
|
||||
|
||||
@property
|
||||
def is_native_tres(self):
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ from markupsafe import Markup
|
|||
#from plots.step_science import *
|
||||
from plots.Dose import *
|
||||
from plots.Temp import *
|
||||
from plots.Counters import *
|
||||
|
||||
from plots.LET import *
|
||||
|
||||
|
|
@ -35,7 +34,7 @@ import MSL.flight_tools as ft
|
|||
|
||||
plot_types = [
|
||||
DoseTimeprofilePlotsB, DoseTimeprofilePlotsE, DoseTimeprofilePlotsB_E
|
||||
, LETPlots,TempTimeprofilePlots,LETPlots_A1B,LETPlots_A2B , CountersTimeprofilePlots_4,CountersTimeprofilePlots_5,CountersTimeprofilePlots_15
|
||||
,Test_plot, LETPlots,TempTimeprofilePlots,LETPlots_A1B,LETPlots_A2B
|
||||
|
||||
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,325 +0,0 @@
|
|||
import datetime as dt
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Dict, Any
|
||||
|
||||
import datetime as dt
|
||||
import pandas as pd
|
||||
import scipy.constants as const
|
||||
|
||||
import numpy as np
|
||||
import scipy.constants as const
|
||||
from time import *
|
||||
import time
|
||||
import MSL.flight_tools as ft
|
||||
import MSL.LET_tools as lt
|
||||
import MSL.time_tools as Mtt
|
||||
#import js2py
|
||||
from backend.plot import Plot, DynamicSpectrumPlot, LinePlot,AccumulatedSpectrumPlot
|
||||
from backend.plotcollection import PlotCollection
|
||||
from bokeh.io import show
|
||||
import os
|
||||
from bokeh.models import ColumnDataSource, HoverTool, Range1d, Label,CustomJS , LogColorMapper, ColorBar, LogTicker, \
|
||||
LogTickFormatter, Title, Whisker
|
||||
|
||||
from bokeh.events import ButtonClick # for saving data
|
||||
from bokeh.models.widgets import DataTable, DateFormatter, TableColumn
|
||||
from bokeh.layouts import grid
|
||||
from bokeh.models import Button # for saving data
|
||||
from bokeh.plotting import output_notebook
|
||||
output_notebook()
|
||||
|
||||
class CountersTimeprofilePlots_4(PlotCollection):
|
||||
"""
|
||||
Plot Total ionising dose
|
||||
"""
|
||||
group = 'RAD_Counters'
|
||||
name = 'Counters(4)'
|
||||
|
||||
def create_plots(self, data: Dict[str, Any]) -> Dict[str, Plot]:
|
||||
|
||||
plot = {'dcounters_4': LinePlot(self, data['counters_4'], title='Counter data (l2mc[4])', ylabel='l2mc[4](count rate)') }
|
||||
t = ([x.strftime("%Y-%m-%d %H:%M:%S")for x in data['counters_4'].index])
|
||||
#print(int(Mtt.posix_to_sol(Mtt.dt_to_posix(t))))
|
||||
A_sol = data['sol']['sol']
|
||||
source = ColumnDataSource({'A_sol':A_sol, 'A_time': t ,'Count_rate_(l2mc[4])': data['counters_4'] })
|
||||
#source = ColumnDataSource(df)
|
||||
#source = ColumnDataSource(data=dict(x=data['dose_B']['B'].index, y=data['dose_B']['B'].value ))
|
||||
button = Button(label="Download", button_type="success")
|
||||
button.js_on_click(CustomJS(args=dict(source=source),code=open(os.path.join(os.path.dirname(__file__),"download.js")).read()))
|
||||
show(button)
|
||||
return(plot)
|
||||
|
||||
|
||||
def load_data(self, start: dt.datetime, end: dt.datetime):
|
||||
#dose = LNDData(start, end).xmas.dose.to_frame()*1e6
|
||||
start_sol = int(Mtt.posix_to_sol(Mtt.dt_to_posix(start)))
|
||||
end_sol = int(Mtt.posix_to_sol(Mtt.dt_to_posix(end)))
|
||||
|
||||
counters = ft.load_data((np.arange(start_sol,end_sol)),load='counters')
|
||||
msk = ft.get_clean_mask(counters)
|
||||
|
||||
counters_= pd.DataFrame(counters['l2mc'],columns = [4],index=pd.DatetimeIndex(Mtt.sol2datetime(counters['sol']),name ='date'))
|
||||
accTime_T= pd.DataFrame(counters,columns = ['accTime_T'],index=pd.DatetimeIndex(Mtt.sol2datetime(counters['sol']),name ='date'))
|
||||
|
||||
frames = [counters_, accTime_T]
|
||||
|
||||
result = pd.concat(frames, axis=1)
|
||||
result["L2_[4]"] = result[4]/result['accTime_T']
|
||||
|
||||
#print(result)
|
||||
|
||||
counters_4= pd.DataFrame(result, columns = ["L2_[4]"],index=pd.DatetimeIndex(Mtt.sol2datetime(counters['sol']),name ='date'))
|
||||
|
||||
#print(counters_4)
|
||||
sol= pd.DataFrame(counters['l2mc'],columns = ['sol'],index=pd.DatetimeIndex(Mtt.sol2datetime(counters['sol']),name ='date'))
|
||||
|
||||
return({'counters_4': counters_4[msk], 'sol': sol[msk]})
|
||||
|
||||
class CountersTimeprofilePlots_5(PlotCollection):
|
||||
"""
|
||||
Plot Total ionising dose
|
||||
"""
|
||||
group = 'RAD_Counters'
|
||||
name = 'Counters(5)'
|
||||
|
||||
def create_plots(self, data: Dict[str, Any]) -> Dict[str, Plot]:
|
||||
|
||||
plot = {'dcounters_5': LinePlot(self, data['counters_5'], title='Counter data (l2mc[5])', ylabel='l2mc[5](count rate)') }
|
||||
t = ([x.strftime("%Y-%m-%d %H:%M:%S")for x in data['counters_5'].index])
|
||||
#print(int(Mtt.posix_to_sol(Mtt.dt_to_posix(t))))
|
||||
A_sol = data['sol']['sol']
|
||||
source = ColumnDataSource({'A_sol':A_sol, 'A_time': t ,'Count_rate_(l2mc[5])': data['counters_5'] })
|
||||
#source = ColumnDataSource(df)
|
||||
#source = ColumnDataSource(data=dict(x=data['dose_B']['B'].index, y=data['dose_B']['B'].value ))
|
||||
button = Button(label="Download", button_type="success")
|
||||
button.js_on_click(CustomJS(args=dict(source=source),code=open(os.path.join(os.path.dirname(__file__),"download.js")).read()))
|
||||
show(button)
|
||||
return(plot)
|
||||
|
||||
|
||||
def load_data(self, start: dt.datetime, end: dt.datetime):
|
||||
#dose = LNDData(start, end).xmas.dose.to_frame()*1e6
|
||||
start_sol = int(Mtt.posix_to_sol(Mtt.dt_to_posix(start)))
|
||||
end_sol = int(Mtt.posix_to_sol(Mtt.dt_to_posix(end)))
|
||||
|
||||
counters = ft.load_data((np.arange(start_sol,end_sol)),load='counters')
|
||||
msk = ft.get_clean_mask(counters)
|
||||
|
||||
counters_= pd.DataFrame(counters['l2mc'],columns = [5],index=pd.DatetimeIndex(Mtt.sol2datetime(counters['sol']),name ='date'))
|
||||
accTime_T= pd.DataFrame(counters,columns = ['accTime_T'],index=pd.DatetimeIndex(Mtt.sol2datetime(counters['sol']),name ='date'))
|
||||
|
||||
frames = [counters_, accTime_T]
|
||||
|
||||
result = pd.concat(frames, axis=1)
|
||||
result["L2_[5]"] = result[5]/result['accTime_T']
|
||||
|
||||
#print(result)
|
||||
|
||||
counters_5= pd.DataFrame(result, columns = ["L2_[5]"],index=pd.DatetimeIndex(Mtt.sol2datetime(counters['sol']),name ='date'))
|
||||
|
||||
#print(counters_4)
|
||||
sol= pd.DataFrame(counters['l2mc'],columns = ['sol'],index=pd.DatetimeIndex(Mtt.sol2datetime(counters['sol']),name ='date'))
|
||||
|
||||
return({'counters_5': counters_5[msk], 'sol': sol[msk]})
|
||||
|
||||
class CountersTimeprofilePlots_15(PlotCollection):
|
||||
"""
|
||||
Plot Total ionising dose
|
||||
"""
|
||||
group = 'RAD_Counters'
|
||||
name = 'Counters(15)'
|
||||
|
||||
def create_plots(self, data: Dict[str, Any]) -> Dict[str, Plot]:
|
||||
|
||||
plot = {'dcounters_15': LinePlot(self, data['counters_15'], title='Counter data (l2mc[15])', ylabel='l2mc[15](count rate)') }
|
||||
t = ([x.strftime("%Y-%m-%d %H:%M:%S")for x in data['counters_15'].index])
|
||||
#print(int(Mtt.posix_to_sol(Mtt.dt_to_posix(t))))
|
||||
A_sol = data['sol']['sol']
|
||||
source = ColumnDataSource({'A_sol':A_sol, 'A_time': t ,'Count_rate_(l2mc[15])': data['counters_15'] })
|
||||
#source = ColumnDataSource(df)
|
||||
#source = ColumnDataSource(data=dict(x=data['dose_B']['B'].index, y=data['dose_B']['B'].value ))
|
||||
button = Button(label="Download", button_type="success")
|
||||
button.js_on_click(CustomJS(args=dict(source=source),code=open(os.path.join(os.path.dirname(__file__),"download.js")).read()))
|
||||
show(button)
|
||||
return(plot)
|
||||
|
||||
|
||||
def load_data(self, start: dt.datetime, end: dt.datetime):
|
||||
#dose = LNDData(start, end).xmas.dose.to_frame()*1e6
|
||||
start_sol = int(Mtt.posix_to_sol(Mtt.dt_to_posix(start)))
|
||||
end_sol = int(Mtt.posix_to_sol(Mtt.dt_to_posix(end)))
|
||||
|
||||
counters = ft.load_data((np.arange(start_sol,end_sol)),load='counters')
|
||||
msk = ft.get_clean_mask(counters)
|
||||
|
||||
counters_= pd.DataFrame(counters['l2mc'],columns = [15],index=pd.DatetimeIndex(Mtt.sol2datetime(counters['sol']),name ='date'))
|
||||
accTime_T= pd.DataFrame(counters,columns = ['accTime_T'],index=pd.DatetimeIndex(Mtt.sol2datetime(counters['sol']),name ='date'))
|
||||
|
||||
frames = [counters_, accTime_T]
|
||||
|
||||
result = pd.concat(frames, axis=1)
|
||||
result["L2_[15]"] = result[15]/result['accTime_T']
|
||||
|
||||
#print(result)
|
||||
|
||||
counters_15= pd.DataFrame(result, columns = ["L2_[15]"],index=pd.DatetimeIndex(Mtt.sol2datetime(counters['sol']),name ='date'))
|
||||
|
||||
#print(counters_4)
|
||||
sol= pd.DataFrame(counters['l2mc'],columns = ['sol'],index=pd.DatetimeIndex(Mtt.sol2datetime(counters['sol']),name ='date'))
|
||||
|
||||
return({'counters_15': counters_15[msk], 'sol': sol[msk]})
|
||||
|
||||
"""
|
||||
class DoseTimeprofilePlotsE(PlotCollection):
|
||||
|
||||
#Plot Total ionising dose
|
||||
|
||||
group = 'Dose-RAD'
|
||||
name = 'Dose-E'
|
||||
|
||||
def create_plots(self, data: Dict[str, Any]) -> Dict[str, Plot]:
|
||||
plot = {'dose_E': LinePlot(self, data['dose_E']*8.64*1e7, title='RAD_E measurements', ylabel='dose rate [mGy/day]') }
|
||||
A_sol = data['sol']['sol']
|
||||
source = ColumnDataSource(({'A_sol':A_sol, 'A_time': ([x.strftime("%Y-%m-%d %H:%M:%S")for x in data['dose_E']['E'].index]),'E_dose [mGy/day]': data['dose_E']['E']*8.64*1e7}))
|
||||
columns = [
|
||||
TableColumn(field='E_dose [mGy/day]', title="E dose rate [mGy/day]"),
|
||||
]
|
||||
|
||||
table = DataTable(
|
||||
source=source,
|
||||
columns=columns,
|
||||
width=400,
|
||||
height=600,
|
||||
sortable=True,
|
||||
selectable=True,
|
||||
editable=True,
|
||||
)
|
||||
|
||||
button = Button(label="Download", button_type="success")
|
||||
button.js_on_click(CustomJS(args=dict(source=source),code=open(os.path.join(os.path.dirname(__file__),"download.js")).read()))
|
||||
show(button)
|
||||
|
||||
return(plot)
|
||||
|
||||
def load_data(self, start: dt.datetime, end: dt.datetime):
|
||||
#dose = LNDData(start, end).xmas.dose.to_frame()*1e6
|
||||
start_sol = int(Mtt.posix_to_sol(Mtt.dt_to_posix(start)))
|
||||
end_sol = int(Mtt.posix_to_sol(Mtt.dt_to_posix(end)))
|
||||
|
||||
dose = ft.load_data((np.arange(start_sol,end_sol)),load='dose', force_timesort=True)
|
||||
msk = ft.get_clean_mask(dose)
|
||||
|
||||
dose_E= pd.DataFrame(dose,columns = ['E'],index=pd.DatetimeIndex(Mtt.sol2datetime(dose['sol']),name ='date'))
|
||||
sol= pd.DataFrame(dose,columns = ['sol'],index=pd.DatetimeIndex(Mtt.sol2datetime(dose['sol']),name ='date'))
|
||||
|
||||
return({'dose_E': dose_E[msk], 'sol': sol[msk]})
|
||||
|
||||
|
||||
class DoseTimeprofilePlotsB_E(PlotCollection):
|
||||
|
||||
#Plot Total ionising dose
|
||||
|
||||
group = 'Dose-RAD'
|
||||
name = 'Dose-BE'
|
||||
def create_plots(self, data: Dict[str, Any]) -> Dict[str, Plot]:
|
||||
plot = {'dose_BE': LinePlot(self, data['dose_BE']*8.64*1e7, title='RAD_BE measurements', ylabel='dose rate [mGy/day]')}
|
||||
A_sol = data['sol']['sol']
|
||||
source = ColumnDataSource(({'A_sol':A_sol, 'A_time': ([x.strftime("%Y-%m-%d %H:%M:%S")for x in data['dose_BE']['B'].index]),'B_dose[mGy/day][per day (i.e., 24 hours), not Sol]': data['dose_BE']['B']*8.64*1e7, 'E_dose[mGy/day][per day (i.e., 24 hours), not Sol]': data['dose_BE']['E']*8.64*1e7}))
|
||||
columns = [
|
||||
TableColumn(field='B_dose [mGy/day]', title="B dose rate [mGy/day]"),
|
||||
TableColumn(field='E_dose [mGy/day]', title="E dose rate [mGy/day]"),
|
||||
]
|
||||
|
||||
table = DataTable(
|
||||
source=source,
|
||||
columns=columns,
|
||||
width=400,
|
||||
height=600,
|
||||
sortable=True,
|
||||
selectable=True,
|
||||
editable=True,
|
||||
)
|
||||
|
||||
button = Button(label="Download", button_type="success")
|
||||
button.js_on_click(CustomJS(args=dict(source=source),code=open(os.path.join(os.path.dirname(__file__),"download.js")).read()))
|
||||
show(button)
|
||||
|
||||
|
||||
return(plot)
|
||||
|
||||
|
||||
def load_data(self, start: dt.datetime, end: dt.datetime):
|
||||
#dose = LNDData(start, end).xmas.dose.to_frame()*1e6
|
||||
start_sol = int(Mtt.posix_to_sol(Mtt.dt_to_posix(start)))
|
||||
end_sol = int(Mtt.posix_to_sol(Mtt.dt_to_posix(end)))
|
||||
|
||||
dose = ft.load_data((np.arange(start_sol,end_sol)),load='dose', force_timesort=True)
|
||||
msk = ft.get_clean_mask(dose, high_dose_resolution=False)
|
||||
|
||||
dose_BE= pd.DataFrame(dose,columns = ['B','E'],index=pd.DatetimeIndex(Mtt.sol2datetime(dose['sol'])))
|
||||
dose_BE.index.name = 'date'
|
||||
#dose_E= pd.DataFrame(dose,columns = ['B'],index=pd.DatetimeIndex(Mtt.sol2datetime(dose['sol']),name ='date'))
|
||||
sol= pd.DataFrame(dose,columns = ['sol'],index=pd.DatetimeIndex(Mtt.sol2datetime(dose['sol']),name ='date'))
|
||||
|
||||
return({'dose_BE': dose_BE[msk], 'sol': sol[msk], 'start':start})
|
||||
|
||||
|
||||
class Test_plot(PlotCollection):
|
||||
name = 'Test Plot'
|
||||
group = 'Test'
|
||||
|
||||
def create_plots(self, data: Dict[str, Any]) -> Dict[str, Plot]:
|
||||
# create two panels, each showing a line plot
|
||||
return {
|
||||
'foo': LinePlot(self, data['foo'],
|
||||
title='Foo measurements',
|
||||
ylabel='Temperature [°C]'),
|
||||
#'bar': LinePlot(self, data['bar'],
|
||||
# title='Bar measurements',
|
||||
# ylabel='Voltage [V]'),
|
||||
}
|
||||
|
||||
def load_data(self, start: dt.datetime, end: dt.datetime):
|
||||
# just generate some example data for the plots:
|
||||
return {
|
||||
'foo': pd.DataFrame({
|
||||
#'a': [2, 2],
|
||||
'b': [2, 1]
|
||||
}, index=pd.DatetimeIndex([start, end], name='date'))
|
||||
#, 'bar': pd.DataFrame({
|
||||
# 'x': [100, 222],
|
||||
# 'y': [111, 150]
|
||||
#}, index=pd.DatetimeIndex([start, end], name='date'))
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# savebutton = Button(label="Save", button_type="success")
|
||||
# callback = CustomJS(
|
||||
# args=dict(source_data=source),
|
||||
# code="""
|
||||
# var inds = source_data.selected.indices;
|
||||
# var data = source_data.data;
|
||||
# var out = "x, y, var inds, var data\\n";
|
||||
# for (var i = 0; i < inds.length; i++) {
|
||||
# out += data['X1'][inds[i]] + "," + data['Y1'][inds[i]] + "," + data['Y2'][inds[i]] +"\\n";
|
||||
# }
|
||||
# var file = new Blob([out], {type: 'text/plain'});
|
||||
# var elem = window.document.createElement('a');
|
||||
# elem.href = window.URL.createObjectURL(file);
|
||||
# elem.download = 'selected-data.txt';
|
||||
# document.body.appendChild(elem);
|
||||
# elem.click();
|
||||
# document.body.removeChild(elem);
|
||||
# """,
|
||||
# )
|
||||
# savebutton.js_on_click(callback)
|
||||
|
||||
# layout = grid([table, savebutton], ncols=2)
|
||||
# show(layout)
|
||||
# out += data['X1'][inds[i]] + "," + data['Y1'][inds[i]] + "," + data['Y2'][inds[i]] +"\\n";
|
||||
#
|
||||
|
||||
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ class DoseTimeprofilePlotsB(PlotCollection):
|
|||
"""
|
||||
Plot Total ionising dose
|
||||
"""
|
||||
group = 'Dose-RAD'
|
||||
group = 'RAD-Dose'
|
||||
name = 'Dose-B'
|
||||
|
||||
def create_plots(self, data: Dict[str, Any]) -> Dict[str, Plot]:
|
||||
|
|
@ -41,23 +41,64 @@ class DoseTimeprofilePlotsB(PlotCollection):
|
|||
t = ([x.strftime("%Y-%m-%d %H:%M:%S")for x in data['dose_B']['B'].index])
|
||||
#print(int(Mtt.posix_to_sol(Mtt.dt_to_posix(t))))
|
||||
A_sol = data['sol']['sol']
|
||||
#print(A_sol)
|
||||
#, 'A_sol':data['sol']
|
||||
source = ColumnDataSource({'A_sol':A_sol, 'A_time': t ,'B_dose [mGy/day]': data['dose_B']['B']*8.64*1e7 })
|
||||
#source = ColumnDataSource(df)
|
||||
#source = ColumnDataSource(data=dict(x=data['dose_B']['B'].index, y=data['dose_B']['B'].value ))
|
||||
#print('here',source.data)
|
||||
#print(source.data)
|
||||
button = Button(label="Download", button_type="success")
|
||||
button.js_on_click(CustomJS(args=dict(source=source),code=open(os.path.join(os.path.dirname(__file__),"download.js")).read()))
|
||||
show(button)
|
||||
return(plot)
|
||||
'''
|
||||
button.js_on_event(ButtonClick, CustomJS(
|
||||
args=dict(source_data=source),
|
||||
code="""
|
||||
var inds = source_data.selected.indices;
|
||||
var data = source_data.data;
|
||||
var nrows = source_data.get_length()
|
||||
var out = "x, y\\n";
|
||||
for (var i = 0; i < nrows; i++) {
|
||||
out += data['dose_B']['B'].index + "," + data['dose_B']['B']*8.64*1e7 + "\\n";
|
||||
}
|
||||
var file = new Blob([out], {type: 'text/plain'});
|
||||
var elem = window.document.createElement('a');
|
||||
elem.href = window.URL.createObjectURL(file);
|
||||
elem.download = 'selected-data.txt';
|
||||
document.body.appendChild(elem);
|
||||
elem.click();
|
||||
document.body.removeChild(elem);
|
||||
"""
|
||||
)
|
||||
)
|
||||
'''
|
||||
"""
|
||||
def create_plots(self, data):
|
||||
#plot = {'Dose-B': plt.plot(data['E'])}
|
||||
print(data['dose_B'])
|
||||
#temp = pd.DataFrame(data['Frontal'])
|
||||
plot = {'dose_B': LinePlot(data['time'],data['dose_B']* 1e6 * 3600*24, title='Total Dose', logy=True,ylabel=r"Total Ionizing Dose[μGy hour⁻¹]")}
|
||||
|
||||
#plot = {'dose_B': plt.plot(data['time'],data['dose_B']* 1e6 * 3600*24)}
|
||||
|
||||
#print(data['B'])
|
||||
return(plot)
|
||||
"""
|
||||
|
||||
def load_data(self, start: dt.datetime, end: dt.datetime):
|
||||
#dose = LNDData(start, end).xmas.dose.to_frame()*1e6
|
||||
#print('here',start)
|
||||
start_sol = int(Mtt.posix_to_sol(Mtt.dt_to_posix(start)))
|
||||
end_sol = int(Mtt.posix_to_sol(Mtt.dt_to_posix(end)))
|
||||
|
||||
#print('I am here', start_sol, end_sol)
|
||||
dose = ft.load_data((np.arange(start_sol,end_sol)),load='dose')
|
||||
msk = ft.get_clean_mask(dose)
|
||||
#print(msk)
|
||||
|
||||
#print("Now here")
|
||||
dose_B= pd.DataFrame(dose,columns = ['B'],index=pd.DatetimeIndex(Mtt.sol2datetime(dose['sol']),name ='date'))
|
||||
sol= pd.DataFrame(dose,columns = ['sol'],index=pd.DatetimeIndex(Mtt.sol2datetime(dose['sol']),name ='date'))
|
||||
|
||||
|
|
@ -67,7 +108,7 @@ class DoseTimeprofilePlotsE(PlotCollection):
|
|||
"""
|
||||
Plot Total ionising dose
|
||||
"""
|
||||
group = 'Dose-RAD'
|
||||
group = 'RAD-Dose'
|
||||
name = 'Dose-E'
|
||||
|
||||
def create_plots(self, data: Dict[str, Any]) -> Dict[str, Plot]:
|
||||
|
|
@ -99,9 +140,11 @@ class DoseTimeprofilePlotsE(PlotCollection):
|
|||
start_sol = int(Mtt.posix_to_sol(Mtt.dt_to_posix(start)))
|
||||
end_sol = int(Mtt.posix_to_sol(Mtt.dt_to_posix(end)))
|
||||
|
||||
#print('I am here', start_sol, end_sol)
|
||||
dose = ft.load_data((np.arange(start_sol,end_sol)),load='dose', force_timesort=True)
|
||||
msk = ft.get_clean_mask(dose)
|
||||
|
||||
#print("Now here")
|
||||
dose_E= pd.DataFrame(dose,columns = ['E'],index=pd.DatetimeIndex(Mtt.sol2datetime(dose['sol']),name ='date'))
|
||||
sol= pd.DataFrame(dose,columns = ['sol'],index=pd.DatetimeIndex(Mtt.sol2datetime(dose['sol']),name ='date'))
|
||||
|
||||
|
|
@ -112,12 +155,15 @@ class DoseTimeprofilePlotsB_E(PlotCollection):
|
|||
"""
|
||||
Plot Total ionising dose
|
||||
"""
|
||||
group = 'Dose-RAD'
|
||||
group = 'RAD-Dose'
|
||||
name = 'Dose-BE'
|
||||
|
||||
def create_plots(self, data: Dict[str, Any]) -> Dict[str, Plot]:
|
||||
#print(data)
|
||||
plot = {'dose_BE': LinePlot(self, data['dose_BE']*8.64*1e7, title='RAD_BE measurements', ylabel='dose rate [mGy/day]')}
|
||||
A_sol = data['sol']['sol']
|
||||
source = ColumnDataSource(({'A_sol':A_sol, 'A_time': ([x.strftime("%Y-%m-%d %H:%M:%S")for x in data['dose_BE']['B'].index]),'B_dose[mGy/day][per day (i.e., 24 hours), not Sol]': data['dose_BE']['B']*8.64*1e7, 'E_dose[mGy/day][per day (i.e., 24 hours), not Sol]': data['dose_BE']['E']*8.64*1e7}))
|
||||
|
||||
source = ColumnDataSource(({'A_sol':A_sol, 'A_time': ([x.strftime("%Y-%m-%d %H:%M:%S")for x in data['dose_BE']['B'].index]),'B_dose [mGy/day]': data['dose_BE']['B']*8.64*1e7, 'E_dose [mGy/day]': data['dose_BE']['E']*8.64*1e7}))
|
||||
columns = [
|
||||
TableColumn(field='B_dose [mGy/day]', title="B dose rate [mGy/day]"),
|
||||
TableColumn(field='E_dose [mGy/day]', title="E dose rate [mGy/day]"),
|
||||
|
|
@ -146,15 +192,18 @@ class DoseTimeprofilePlotsB_E(PlotCollection):
|
|||
start_sol = int(Mtt.posix_to_sol(Mtt.dt_to_posix(start)))
|
||||
end_sol = int(Mtt.posix_to_sol(Mtt.dt_to_posix(end)))
|
||||
|
||||
#print('I am here', start_sol, end_sol)
|
||||
dose = ft.load_data((np.arange(start_sol,end_sol)),load='dose', force_timesort=True)
|
||||
msk = ft.get_clean_mask(dose, high_dose_resolution=False)
|
||||
msk = ft.get_clean_mask(dose)
|
||||
#print(msk)
|
||||
|
||||
#print("Now here")
|
||||
dose_BE= pd.DataFrame(dose,columns = ['B','E'],index=pd.DatetimeIndex(Mtt.sol2datetime(dose['sol'])))
|
||||
dose_BE.index.name = 'date'
|
||||
#dose_E= pd.DataFrame(dose,columns = ['B'],index=pd.DatetimeIndex(Mtt.sol2datetime(dose['sol']),name ='date'))
|
||||
sol= pd.DataFrame(dose,columns = ['sol'],index=pd.DatetimeIndex(Mtt.sol2datetime(dose['sol']),name ='date'))
|
||||
|
||||
return({'dose_BE': dose_BE[msk], 'sol': sol[msk], 'start':start})
|
||||
return({'dose_BE': dose_BE[msk], 'sol': sol[msk]})
|
||||
|
||||
|
||||
class Test_plot(PlotCollection):
|
||||
|
|
|
|||
BIN
plots/__pycache__/Dose.cpython-37.pyc
Normal file
BIN
plots/__pycache__/Dose.cpython-37.pyc
Normal file
Binary file not shown.
BIN
plots/__pycache__/LET.cpython-37.pyc
Normal file
BIN
plots/__pycache__/LET.cpython-37.pyc
Normal file
Binary file not shown.
BIN
plots/__pycache__/Temp.cpython-37.pyc
Normal file
BIN
plots/__pycache__/Temp.cpython-37.pyc
Normal file
Binary file not shown.
BIN
plots/__pycache__/__init__.cpython-37.pyc
Normal file
BIN
plots/__pycache__/__init__.cpython-37.pyc
Normal file
Binary file not shown.
BIN
plots/__pycache__/combined_spectra.cpython-37.pyc
Normal file
BIN
plots/__pycache__/combined_spectra.cpython-37.pyc
Normal file
Binary file not shown.
BIN
plots/__pycache__/ept_science.cpython-37.pyc
Normal file
BIN
plots/__pycache__/ept_science.cpython-37.pyc
Normal file
Binary file not shown.
BIN
plots/__pycache__/het_science.cpython-37.pyc
Normal file
BIN
plots/__pycache__/het_science.cpython-37.pyc
Normal file
Binary file not shown.
BIN
plots/__pycache__/housekeeping.cpython-37.pyc
Normal file
BIN
plots/__pycache__/housekeeping.cpython-37.pyc
Normal file
Binary file not shown.
BIN
plots/__pycache__/mag.cpython-37.pyc
Normal file
BIN
plots/__pycache__/mag.cpython-37.pyc
Normal file
Binary file not shown.
BIN
plots/__pycache__/step_science.cpython-37.pyc
Normal file
BIN
plots/__pycache__/step_science.cpython-37.pyc
Normal file
Binary file not shown.
BIN
plots/__pycache__/utils.cpython-37.pyc
Normal file
BIN
plots/__pycache__/utils.cpython-37.pyc
Normal file
Binary file not shown.
308
plots/het_science.py
Normal file
308
plots/het_science.py
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
import datetime as dt
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Dict, Any
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import scipy.constants as const
|
||||
from etspice import SOLO
|
||||
from solo_loader.epd import EPDData
|
||||
from solo_loader.exception import ConfigurationChangeError
|
||||
from solo_loader.processing.velocity_dispersion import inv_velocity_spectrum, parker_spiral_length
|
||||
|
||||
from backend.plot import Plot, DynamicSpectrumPlot, LinePlot
|
||||
from backend.plotcollection import PlotCollection
|
||||
from plots.utils import handle_config_changes
|
||||
|
||||
|
||||
class HETDynamicSpectrumPlots(PlotCollection, ABC):
|
||||
"""
|
||||
Plots an HET dynamic spectrum
|
||||
"""
|
||||
group = 'HET SCI'
|
||||
|
||||
titles = {
|
||||
'sun': 'Sunward',
|
||||
'asun': 'Anti-Sunward',
|
||||
'north': 'Northward',
|
||||
'south': 'Southward'
|
||||
}
|
||||
particles = {
|
||||
'p': 'protons',
|
||||
'e': 'electrons'
|
||||
}
|
||||
|
||||
def create_plots(self, data: Dict[str, Any]) -> Dict[str, Plot]:
|
||||
plots = {}
|
||||
for direction in data:
|
||||
dfs = data[direction]
|
||||
|
||||
# share colorbar with sun plot
|
||||
share_colorbar = plots['sun'] if direction != 'sun' else None
|
||||
|
||||
plots[direction] = DynamicSpectrumPlot(self,
|
||||
dfs,
|
||||
title=f'{self.titles[direction]} HET {self.particles[self.species]}',
|
||||
data_label='diff. flux /\n(cm² sr s keV)⁻¹', logy=True,
|
||||
share_colorbar=share_colorbar, ylabel='E / MeV')
|
||||
return plots
|
||||
|
||||
def load_data(self, start, end):
|
||||
epd = EPDData(start, end)
|
||||
if self.nominal:
|
||||
fun = lambda x: x.het.science.nominal
|
||||
else:
|
||||
fun = lambda x: x.het.science.low_latency
|
||||
|
||||
if self.species == 'e':
|
||||
types = ['B', 'C'] # electrons are only available in "stopping in B" and "stopping in C" trigger
|
||||
else:
|
||||
types = ['B', 'C', 'P'] # stopping in B, stopping in C, penetrating
|
||||
|
||||
try:
|
||||
data = [fun(epd)(self.species, t) for t in types]
|
||||
except ConfigurationChangeError as e:
|
||||
# split loading of data between configuration changes
|
||||
data = [fun(part)(self.species, t) for part in handle_config_changes(epd, e) for t in types]
|
||||
|
||||
fluxes = {}
|
||||
for direction in ['sun', 'asun', 'north', 'south']:
|
||||
dfs = [df[direction].to_flux(edges=True) for df in data]
|
||||
for df in dfs:
|
||||
df.columns = pd.IntervalIndex.from_arrays(df.columns.left / 1e3, df.columns.right / 1e3)
|
||||
df.columns.name = "primary energy / MeV"
|
||||
fluxes[direction] = dfs
|
||||
return fluxes
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def species(self) -> str:
|
||||
pass
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def nominal(self) -> bool:
|
||||
pass
|
||||
|
||||
|
||||
class HETDynamicSpectrumLLProtonPlots(HETDynamicSpectrumPlots):
|
||||
name = 'Dynamic Spectrum (LL, Protons)'
|
||||
nominal = False
|
||||
species = 'p'
|
||||
|
||||
|
||||
class HETDynamicSpectrumNominalProtonPlots(HETDynamicSpectrumPlots):
|
||||
name = 'Dynamic Spectrum (NO, Protons)'
|
||||
nominal = True
|
||||
species = 'p'
|
||||
|
||||
|
||||
class HETDynamicSpectrumLLElectronPlots(HETDynamicSpectrumPlots):
|
||||
name = 'Dynamic Spectrum (LL, Electrons)'
|
||||
nominal = False
|
||||
species = 'e'
|
||||
|
||||
|
||||
class HETDynamicSpectrumNominalElectronPlots(HETDynamicSpectrumPlots):
|
||||
name = 'Dynamic Spectrum (NO, Electrons)'
|
||||
nominal = True
|
||||
species = 'e'
|
||||
|
||||
|
||||
titles_p = {
|
||||
'sun': 'Sunward HET protons',
|
||||
'asun': 'Anti-Sunward HET protons',
|
||||
'north': 'Northward HET protons',
|
||||
'south': 'Southward HET protons'
|
||||
}
|
||||
|
||||
titles_e = {
|
||||
'sun': 'Sunward HET electrons',
|
||||
'asun': 'Anti-Sunward HET electrons',
|
||||
'north': 'Northward HET electrons',
|
||||
'south': 'Southward HET electrons'
|
||||
}
|
||||
|
||||
|
||||
def columns_to_mev(df):
|
||||
df.columns = ['{:.1f} MeV'.format(energy / 1e3) for energy in df.columns]
|
||||
|
||||
|
||||
class HETTimeProfilesPlotsProtons(PlotCollection):
|
||||
name = 'Time Profiles Proton'
|
||||
group = 'HET SCI'
|
||||
|
||||
def create_plots(self, data: Dict[str, Any]) -> Dict[str, Plot]:
|
||||
return {
|
||||
key: LinePlot(self, data[key], title=titles_p[key], logy=True,
|
||||
ylabel='diff. particle flux / (mm² sr s keV)⁻¹')
|
||||
for key in data
|
||||
}
|
||||
|
||||
def load_data(self, start: dt.datetime, end: dt.datetime):
|
||||
epd = EPDData(start, end)
|
||||
data = {}
|
||||
|
||||
try:
|
||||
het_pB = [epd.het.science.low_latency('p', 'B')]
|
||||
het_pC = [epd.het.science.low_latency('p', 'C')]
|
||||
het_pP = [epd.het.science.low_latency('p', 'P')]
|
||||
except ConfigurationChangeError as e:
|
||||
# split loading of data between configuration changes
|
||||
het_pB = [part.het.science.low_latency('p', 'B') for part in handle_config_changes(epd, e)]
|
||||
het_pC = [part.het.science.low_latency('p', 'C') for part in handle_config_changes(epd, e)]
|
||||
het_pP = [part.het.science.low_latency('p', 'P') for part in handle_config_changes(epd, e)]
|
||||
|
||||
for direction in ['sun', 'asun', 'north', 'south']:
|
||||
p_pds = pd.concat([
|
||||
pd.concat([b[direction].to_flux(),
|
||||
c[direction].to_flux(),
|
||||
p[direction].to_flux()], axis=1)
|
||||
for b, c, p in zip(het_pB, het_pC, het_pP)]).resample('30min').mean()
|
||||
columns_to_mev(p_pds)
|
||||
|
||||
data[direction] = p_pds
|
||||
return data
|
||||
|
||||
|
||||
class HETTimeProfilesPlotsElectrons(PlotCollection):
|
||||
name = 'Time Profiles Electron'
|
||||
group = 'HET SCI'
|
||||
|
||||
def create_plots(self, data: Dict[str, Any]) -> Dict[str, Plot]:
|
||||
return {
|
||||
key: LinePlot(self, data[key], title=titles_e[key], logy=True,
|
||||
ylabel='diff. particle flux / (mm² sr s keV)⁻¹')
|
||||
for key in data
|
||||
}
|
||||
|
||||
def load_data(self, start: dt.datetime, end: dt.datetime):
|
||||
epd = EPDData(start, end)
|
||||
data = {}
|
||||
|
||||
try:
|
||||
het_eB = [epd.het.science.low_latency('e', 'B')]
|
||||
het_eC = [epd.het.science.low_latency('e', 'C')]
|
||||
except ConfigurationChangeError as e:
|
||||
# split loading of data between configuration changes
|
||||
het_eB = [part.het.science.low_latency('e', 'B') for part in handle_config_changes(epd, e)]
|
||||
het_eC = [part.het.science.low_latency('e', 'C') for part in handle_config_changes(epd, e)]
|
||||
|
||||
for direction in ['sun', 'asun', 'north', 'south']:
|
||||
p_pds = pd.concat([
|
||||
pd.concat([b[direction].to_flux(),
|
||||
c[direction].to_flux()], axis=1)
|
||||
for b, c in zip(het_eB, het_eC)]).resample('30min').mean()
|
||||
columns_to_mev(p_pds)
|
||||
|
||||
data[direction] = p_pds
|
||||
return data
|
||||
|
||||
|
||||
class HETVelocityDispersion(PlotCollection):
|
||||
name = 'Velocity Dispersion'
|
||||
group = 'HET SCI'
|
||||
|
||||
def create_plots(self, data: Dict[str, Any]) -> Dict[str, Plot]:
|
||||
plots = {}
|
||||
|
||||
titles = {
|
||||
'sun protons': 'Sunward Pointing Detector, protons',
|
||||
'asun protons': 'Anti-Sunward Pointing Detector, protons',
|
||||
'north protons': 'Northward Pointing Detector, protons',
|
||||
'south protons': 'Southward Pointing Detector, protons',
|
||||
'sun electrons': 'Sunward Pointing Detector, electrons',
|
||||
'asun electrons': 'Anti-Sunward Pointing Detector, electrons',
|
||||
'north electrons': 'Northward Pointing Detector, electrons',
|
||||
'south electrons': 'Southward Pointing Detector, electrons'
|
||||
}
|
||||
for key in data:
|
||||
# share colorbar with sun plot
|
||||
share_colorbar = plots['sun ' + key.split(' ')[1]] if not key.startswith('sun') else None
|
||||
plots[key] = DynamicSpectrumPlot(self, data[key], title=titles[key],
|
||||
share_colorbar=share_colorbar, data_label='flux / counts/(s mm² sr keV)',
|
||||
ylabel='1/v / h/AU')
|
||||
|
||||
# for pos in np.linspace(0, 1, 5):
|
||||
# plot diagonal lines
|
||||
# plot_diagonal(ax, (pos, 0), slope, color='k')
|
||||
return plots # and diagonals
|
||||
|
||||
def load_data(self, start, end):
|
||||
epd = EPDData(start, end)
|
||||
het = epd.het
|
||||
try:
|
||||
dfs_p_B = [het.science.low_latency('p', 'B')]
|
||||
dfs_p_C = [het.science.low_latency('p', 'C')]
|
||||
dfs_p_P = [het.science.low_latency('p', 'P')]
|
||||
dfs_e_B = [het.science.low_latency('e', 'B')]
|
||||
dfs_e_C = [het.science.low_latency('e', 'C')]
|
||||
except ConfigurationChangeError as e:
|
||||
# split loading of data between configuration changes
|
||||
dfs_p_B = [part.ept.science.low_latency('p', 'B') for part in handle_config_changes(epd, e)]
|
||||
dfs_p_C = [part.ept.science.low_latency('p', 'C') for part in handle_config_changes(epd, e)]
|
||||
dfs_p_P = [part.ept.science.low_latency('p', 'P') for part in handle_config_changes(epd, e)]
|
||||
dfs_e_B = [part.ept.science.low_latency('e', 'B') for part in handle_config_changes(epd, e)]
|
||||
dfs_e_C = [part.ept.science.low_latency('e', 'C') for part in handle_config_changes(epd, e)]
|
||||
|
||||
data = {}
|
||||
|
||||
for direction in ['sun', 'asun', 'north', 'south']:
|
||||
data[f'{direction} protons'] = pd.concat([
|
||||
pd.concat([inv_velocity_spectrum(b[direction].to_flux(edges=True), mass=const.m_p),
|
||||
inv_velocity_spectrum(c[direction].to_flux(edges=True), mass=const.m_p),
|
||||
inv_velocity_spectrum(p[direction].to_flux(edges=True), mass=const.m_p)], axis=1)
|
||||
for b, c, p in zip(dfs_p_B, dfs_p_C, dfs_p_P)]).resample('30min').mean()
|
||||
data[f'{direction} electrons'] = pd.concat([
|
||||
pd.concat([inv_velocity_spectrum(b[direction].to_flux(edges=True), mass=const.m_e),
|
||||
inv_velocity_spectrum(c[direction].to_flux(edges=True), mass=const.m_e)])
|
||||
for b, c in zip(dfs_e_B, dfs_e_C)]).resample('30min').mean()
|
||||
|
||||
# get the position of SolO referred to the sun
|
||||
position = SOLO.position((end - start) / 2 + start)
|
||||
# get the total distance from SolO to the sun
|
||||
distance = np.linalg.norm(position)
|
||||
# convert from km to au
|
||||
distance = distance / const.au * 1e3
|
||||
# get the distance along the parker spiral
|
||||
slope = parker_spiral_length(distance, v_sw=400)
|
||||
# multiply by 24 because matplotlib represents dates as days since epoch, not hours
|
||||
slope *= 24
|
||||
|
||||
return data
|
||||
|
||||
|
||||
class HETGCRPlots(PlotCollection):
|
||||
name = 'GCR counters'
|
||||
group = 'HET SCI'
|
||||
|
||||
def create_plots(self, data: Dict[str, Any]) -> Dict[str, Plot]:
|
||||
return {
|
||||
'c_counters': LinePlot(self, data['c_counters'],
|
||||
title=f'HET C detector counters (isotropic GCR ≳ 15 MeV/nuc)', ylabel='counts / s'),
|
||||
'gcr_channel': LinePlot(self, data['gcr_channel'],
|
||||
title=f'HET GCR channel (BCB penetrating GCR ≳ 100 MeV/nuc)', ylabel='counts / s')
|
||||
}
|
||||
|
||||
def load_data(self, start: dt.datetime, end: dt.datetime):
|
||||
# sum all C high gain and all C low gain channels
|
||||
c_counters = pd.DataFrame({
|
||||
channel: pd.concat([
|
||||
EPDData(start, end).het.housekeeping.l1_counters(unit)[[f'C1{channel}', f'C2{channel}']]
|
||||
.sum(axis=1).resample('10min').sum(min_count=1) / 600
|
||||
for unit in ['he1', 'he2']
|
||||
], axis=1).sum(axis=1, skipna=False)
|
||||
for channel in ['H', 'L']
|
||||
})
|
||||
# GCR channel
|
||||
gcr = EPDData(start, end).het.science.gcr()
|
||||
gcr = pd.DataFrame({
|
||||
key: gcr[key].sum(axis=1, skipna=False).resample('60min').sum(min_count=1) / 3600
|
||||
for key in gcr
|
||||
})
|
||||
for key in gcr:
|
||||
gcr[f'{key} (smoothed)'] = gcr[key].rolling(10, center=True).mean()
|
||||
return {
|
||||
'c_counters': c_counters,
|
||||
'gcr_channel': gcr
|
||||
}
|
||||
BIN
widgets/__pycache__/__init__.cpython-37.pyc
Normal file
BIN
widgets/__pycache__/__init__.cpython-37.pyc
Normal file
Binary file not shown.
BIN
widgets/__pycache__/dataproduct_select.cpython-37.pyc
Normal file
BIN
widgets/__pycache__/dataproduct_select.cpython-37.pyc
Normal file
Binary file not shown.
BIN
widgets/__pycache__/save_action.cpython-37.pyc
Normal file
BIN
widgets/__pycache__/save_action.cpython-37.pyc
Normal file
Binary file not shown.
BIN
widgets/__pycache__/svg_action.cpython-37.pyc
Normal file
BIN
widgets/__pycache__/svg_action.cpython-37.pyc
Normal file
Binary file not shown.
BIN
widgets/__pycache__/txt_action.cpython-37.pyc
Normal file
BIN
widgets/__pycache__/txt_action.cpython-37.pyc
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue