Skip to content

Commit

Permalink
Merge branch 'refs/heads/develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
Philipp Kraft committed Aug 7, 2024
2 parents 462383e + e6d0927 commit ae0b431
Show file tree
Hide file tree
Showing 11 changed files with 513 additions and 120 deletions.
2 changes: 1 addition & 1 deletion odmf/plot/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .plot import Line, Subplot, Plot
from .plot import Line, Subplot, Plot, NoDataError
4 changes: 2 additions & 2 deletions odmf/plot/draw_mpl.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def _draw_subplot(subplot: Subplot, ax: Axes, start: datetime.datetime, end: dat
ax.text(x, ax.get_ylim()[0], logtype,
ha='left', va='bottom', fontsize=subplot.plot.fontsize(0.9))

ax.set_xlim(subplot.plot.start, subplot.plot.end)
ax.set_xlim(*subplot.plot.get_time_span())

for xtl in ax.get_xticklabels():
xtl.set_rotation(15)
Expand All @@ -73,7 +73,7 @@ def _draw_plot(plot: Plot) -> Figure:
fig, axes = plt.subplots(ncols=plot.columns, nrows=rows, squeeze=False,
figsize=size_inch, dpi=100, sharex='all')
for sp, ax in zip(plot.subplots, axes.ravel()):
_draw_subplot(sp, ax, plot.start, plot.end)
_draw_subplot(sp, ax, *plot.get_time_span())

fig.subplots_adjust(top=0.975, bottom=0.1, hspace=0.0)
return fig
Expand Down
2 changes: 1 addition & 1 deletion odmf/plot/draw_plotly.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def _make_figure(plot: Plot) -> go.Figure:
fig.update_yaxes()
fig.add_traces(
[
_draw_line(l, plot.start, plot.end)
_draw_line(l, *plot.get_time_span())
for l in plot.lines()
],
rows=rows,
Expand Down
60 changes: 43 additions & 17 deletions odmf/plot/plot.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from datetime import datetime, timedelta

import pandas as pd
from .. import db

class NoDataError(ValueError):
...

def asdict(obj):
"""
Expand Down Expand Up @@ -49,7 +51,7 @@ def __init__(self, subplot, valuetype, site, instrument=None, level=None,
self.aggregatefunction = aggregatefunction
self.name = name or self.generate_name()
if not (linestyle or marker):
raise ValueError('Lines need either a linestyle or a marker for the creation')
raise NoDataError('Lines need either a linestyle or a marker for the creation')

def generate_name(self):
"""
Expand All @@ -76,11 +78,12 @@ def getdatasets(self, session):
"""
from ..webpage.auth import users
me = users.current
start, end = self.subplot.plot.get_time_span()
datasets = session.query(db.Dataset).filter(
db.Dataset._valuetype == self.valuetypeid,
db.Dataset._site == self.siteid,
db.Dataset.start <= self.subplot.plot.end,
db.Dataset.end >= self.subplot.plot.start
db.Dataset.start <= end,
db.Dataset.end >= start
)
if self.instrumentid:
datasets = datasets.filter(db.Dataset._source == self.instrumentid)
Expand All @@ -96,25 +99,24 @@ def load(self, start=None, end=None):
Loads the records into an array
"""
with db.session_scope() as session:
end = end or self.subplot.plot.end
start = start or self.subplot.plot.start
plot_timespan = self.subplot.plot.get_time_span()
end = end or plot_timespan[1]
start = start or plot_timespan[0]
datasets = self.getdatasets(session)
if not datasets:
raise ValueError("No data to compute")
group = db.DatasetGroup([ds.id for ds in datasets], start, end)
series = group.asseries(session, self.name)
if datasets:
group = db.DatasetGroup([ds.id for ds in datasets], start, end)
series = group.asseries(session, self.name)
else:
series = pd.Series([])

if self.subplot.plot.aggregate:
if self.subplot.plot.aggregate and not series.empty:
if self.subplot.plot.aggregate == 'decade':
from ..tools.exportdatasets import DecadeMonthStart
sampler = series.resample(DecadeMonthStart())
else:
sampler = series.resample(self.subplot.plot.aggregate)
series = sampler.aggregate(self.aggregatefunction or 'mean')

# There were problems with arrays from length 0
if series.empty:
raise ValueError("No data to compute")
series.name = str(self)
return series

Expand Down Expand Up @@ -180,10 +182,11 @@ def __iter__(self):
return iter(self.lines)

def get_logs(self):
start, end = self.plot.get_time_span()
with db.session_scope() as session:
# Get logbook entries for logsite during the plot-time
logs = session.query(db.Log).filter_by(_site=self.logsite).filter(
db.Log.time >= self.plot.start).filter(db.Log.time <= self.plot.end)
db.Log.time >= start).filter(db.Log.time <= end)
return [
(log.time, log.type, str(log))
for log in logs
Expand Down Expand Up @@ -224,8 +227,18 @@ def __init__(self, height=None, width=None, columns=None, start=None, end=None,
@param start: Date for the beginning x axis
@param end: Date of the end of the x axis
"""
self.start = start or datetime.today() - timedelta(days=90)
self.end = end or datetime.today()
if isinstance(start, str):
if start[0] == '-':
start = int(start)
else:
start = pd.to_datetime(start).to_pydatetime()
if isinstance(end, str):
if end[0] == '-':
end = int(end)
else:
end = pd.to_datetime(end).to_pydatetime()
self.start = start or -90
self.end = end or -90
self.size = (width or 640, height or 480)
self.columns = columns or 1
self.subplots = []
Expand All @@ -239,6 +252,19 @@ def __init__(self, height=None, width=None, columns=None, start=None, end=None,

self.args = kwargs

def get_time_span(self):
"""
Returns the time span for the plot
"""
if isinstance(self.start, int):
end = datetime.today()
start = end + timedelta(days=self.start)
return start, end
else:
return (self.start or datetime.today() - timedelta(days=90),
self.end or datetime.today())


def lines(self):

return [line for sp in self.subplots for line in sp.lines]
Expand Down
50 changes: 50 additions & 0 deletions odmf/static/media/help/plot/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Plotting data

Plots are the prime place to get data - either for visual inspection or for
export. Plots are defined with general properties !fa-cog , subplots and
lines. The lines define the data to be shown.

## !fa-chart-line The plot content

### Subplots

You start with an empty plot and you can !fa-plus-circle add subplots (common time axis) to the plot. The subplot can be changed with:

- !fa-trash : delete subplot
- <i>y</i>&#x2195 : set y axis to a fixed range
- !fa-tags : show log messages for a certain site

### Lines
Then you !fa-plus-circle add data lines to the subplot. You can leave the name of
a line empty. Select the datassets by valuetype, site, level and instrument.
In case of an aggregated plot, ypu can select one of the aggregation functions.

Use markers, line styles, colors and width to seperate lines in a subplot visually.

After creation of a line you can click on it to drop down the line tools:

- !fa-trash : remove line
- !fa-list : show datasets of this line
- !fa-edit : Change the line properties
- !fa-copy : Copy this line and start editing


## !fa-cog Properties

Here you describe how the plot as a whole functions, which timespan, the layout of subplots, the aggregation and you can describe the figure

### !fa-clock Time span

Select the timespan for the plot.

## !fa-file load / save plot

Give the subplot a name and select a fitting directory in the filemanager. Plot files can be opened
from the file manager also.

## !fa-file-export Export data

See help:export



101 changes: 101 additions & 0 deletions odmf/static/media/images/odmf-short.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
125 changes: 125 additions & 0 deletions odmf/static/media/images/odmf.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 44 additions & 15 deletions odmf/static/media/js/plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@


function seterror(jqhxr ,textStatus, errorThrown) {
set_error(textStatus)
set_error(jqhxr.responseText)
}

function gettime(startOrEnd) {
let timespan = $('#timeselect').val()
if (timespan < 0) {
return timespan * 1;
}
let res = $('#'+ startOrEnd + 'date').val();
if (res) {
res += ' ' + ($('#'+ startOrEnd + 'time').val() || '00:00');
res += ' ' + ($('#'+ startOrEnd + 'time').val() || '00:00:00');
} else {
let today = new Date();
if (startOrEnd == 'start') {
Expand Down Expand Up @@ -123,18 +127,14 @@ class Plot {
this.subplots = saved_plot.subplots || []

} else {
this.name = ''
this.name = 'Unnamed plot'
this.start = gettime('start')
this.end = gettime('end')
this.columns = 1
this.aggregate = ''
this.height = 640
this.width = 480
this.subplots = [{
lines: [],
ylim: null,
logsite: null,
}]
this.subplots = []

}
}
Expand All @@ -147,8 +147,9 @@ class Plot {
this.apply()
return this
}
render() {
render(do_apply=true) {
$('#plot').html('Loading image...');
let startTime = Date.now()
$.ajax({
method: 'POST',
url: odmf_ref('/plot/figure'),
Expand All @@ -161,10 +162,20 @@ class Plot {
$('#plot').html(result);
$('#plot-reload-button').addClass('d-none')
$('#plot').removeClass('semitransparent')
$('#error-row').addClass('d-none')
set_error('')
let renderTime = Date.now() - startTime
$('#rendertime').html(renderTime.toString() + ' ms')
if (renderTime > 1000) {
$('#autoreload_switch').prop('checked', false)
}
})
.fail(seterror);
return this.apply()
if (do_apply) {
return this.apply()
} else {
return this
}

}

addsubplot() {
Expand All @@ -184,6 +195,7 @@ class Plot {
let txt_plot = JSON.stringify(this, null, 4);
$('#plot-name').html(this.name)
$('#content-tree .subplot').remove();
let autoreload = $('#autoreload_switch').prop('checked');
this.subplots.forEach((subplot, index) => {
let txt = $('#subplot-template').html()
.replace(/§position§/g, index)
Expand All @@ -202,11 +214,17 @@ class Plot {
$('#ct-new-subplot').before(obj);
})
sessionStorage.setItem('plot', txt_plot);
$('#property-summary').html(plot.toString())
$('#json-row pre').html(txt_plot);
$('#plot-reload-button').css('top',this.height / 2).css('left', this.width / 3).removeClass('d-none')
$('#plot').addClass('semitransparent')
set_content_tree_handlers();
return this
if (autoreload) {
return this.render(false);
} else {
$('#plot-reload-button').css('top',this.height / 2).css('left', this.width / 3).removeClass('d-none')
$('#plot').addClass('semitransparent')
return this
}

}
removesubplot(id) {
this.subplots.splice(id, 1);
Expand Down Expand Up @@ -241,6 +259,13 @@ class Plot {
sp.lines.splice(line, 1);
return this
}

toString() {
if (this.start < 0) {
return 'last ' + (this.start*-1) + ' days, aggregate: ' + this.aggregate
}
return this.start.toString().slice(0,10) + ' - ' + this.end.toString().slice(0,10) + ', aggregate: ' + this.aggregate
}
}

function line_from_dialog() {
Expand Down Expand Up @@ -477,7 +502,7 @@ $(() => {

set_line_dialog_handlers()

$('#reload_plot').on('click', () => {
$('.do-reload').on('click', () => {
window.plot.render()
});

Expand All @@ -503,6 +528,10 @@ $(() => {
if (confirm('Do you really want to delete your plot "' + fn + '" from the server'))
$.post('deleteplotfile',{filename:fn},seterror);
});
$('#autoreload_div').on('click', event => {
alert('hä?')
window.plot.render()
})
});


Expand Down
Loading

0 comments on commit ae0b431

Please sign in to comment.