diff --git a/.github/workflows/docker_deploy.yml b/.github/workflows/docker_deploy.yml
new file mode 100644
index 0000000..dcddace
--- /dev/null
+++ b/.github/workflows/docker_deploy.yml
@@ -0,0 +1,38 @@
+on:
+ push:
+ # branches: ['release']
+ workflow_dispatch:
+
+env:
+ REGISTRY: ghcr.io
+ IMAGE_NAME: roman-dvorak/DOSPORTAL/web
+
+jobs:
+ build-and-push-image:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ - name: Log in to the Container registry
+ uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+ - name: Extract metadata (tags, labels) for Docker
+ id: meta
+ uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
+ with:
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
+ - name: Build and push Docker image
+ uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
+ with:
+ context: .
+ file: Dockerfile
+ push: true
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
diff --git a/DOSPORTAL/detectors/__init__.py b/DOSPORTAL/detectors/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/DOSPORTAL/forms.py b/DOSPORTAL/forms.py
index e69de29..d5155ee 100644
--- a/DOSPORTAL/forms.py
+++ b/DOSPORTAL/forms.py
@@ -0,0 +1,53 @@
+from django import forms
+from .models import Detector, record
+
+
+class DetectorLogblogForm(forms.Form):
+ text = forms.CharField(
+ widget=forms.Textarea(
+ attrs={
+ 'class': 'form-control'
+ }
+ )
+ )
+
+
+
+class RecordForm(forms.ModelForm):
+ log_file = forms.FileField(
+ required=False,
+ widget=forms.widgets.FileInput(attrs={
+ 'class': 'form-control',
+ }),
+ label="Log file",
+ #widget=forms.FileInput(attrs={
+ # 'class': 'form-control',
+ #})
+ )
+
+ detector = forms.ModelChoiceField(
+ queryset=Detector.objects.all(),
+ widget=forms.Select(attrs={
+ 'class': 'form-control',
+ }),
+ required=False
+ )
+
+ record_type = forms.ChoiceField(
+ choices=record.RECORD_TYPES,
+ widget=forms.Select(attrs={
+ 'class': 'form-control',
+ })
+ )
+
+ time_start = forms.DateTimeField(
+ widget=forms.DateTimeInput(attrs={
+ 'type': "datetime-local",
+ 'class': 'form-control datetimepicker-input',
+ })
+ )
+
+
+ class Meta:
+ model = record
+ exclude = ("time_end", "measurement", "log_filename", "metadata", "duration")
diff --git a/DOSPORTAL/migrations/0030_alter_flight_cari_alter_measurement_flight.py b/DOSPORTAL/migrations/0030_alter_flight_cari_alter_measurement_flight.py
index 2da239d..87b98db 100644
--- a/DOSPORTAL/migrations/0030_alter_flight_cari_alter_measurement_flight.py
+++ b/DOSPORTAL/migrations/0030_alter_flight_cari_alter_measurement_flight.py
@@ -1,4 +1,4 @@
-# Generated by Django 4.2.5 on 2023-09-25 07:29
+# Generated by Django 4.2.7 on 2023-12-03 10:54
from django.db import migrations, models
import django.db.models.deletion
diff --git a/DOSPORTAL/migrations/0031_detectorlogbook_public.py b/DOSPORTAL/migrations/0031_detectorlogbook_public.py
new file mode 100644
index 0000000..c934c87
--- /dev/null
+++ b/DOSPORTAL/migrations/0031_detectorlogbook_public.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.7 on 2023-12-03 16:09
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('DOSPORTAL', '0030_alter_flight_cari_alter_measurement_flight'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='detectorlogbook',
+ name='public',
+ field=models.BooleanField(default=True),
+ ),
+ ]
diff --git a/DOSPORTAL/migrations/0032_detector_data_alter_detectorlogbook_public_and_more.py b/DOSPORTAL/migrations/0032_detector_data_alter_detectorlogbook_public_and_more.py
new file mode 100644
index 0000000..4169079
--- /dev/null
+++ b/DOSPORTAL/migrations/0032_detector_data_alter_detectorlogbook_public_and_more.py
@@ -0,0 +1,29 @@
+# Generated by Django 4.2.7 on 2023-12-03 17:21
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('DOSPORTAL', '0031_detectorlogbook_public'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='detector',
+ name='data',
+ field=models.JSONField(default={}, help_text='Detector metadata, used for advanced data processing and maintaining', verbose_name='Detector data'),
+ preserve_default=False,
+ ),
+ migrations.AlterField(
+ model_name='detectorlogbook',
+ name='public',
+ field=models.BooleanField(default=True, help_text='Private logbook will be visible for maintainers of detector and for dosportal admins.', verbose_name='Wish to be visible to everyone?'),
+ ),
+ migrations.AlterField(
+ model_name='detectorlogbook',
+ name='text',
+ field=models.TextField(help_text='Detailed description of activity made on the detector.', verbose_name='Logbook text'),
+ ),
+ ]
diff --git a/DOSPORTAL/migrations/0033_detector_manufactured_date.py b/DOSPORTAL/migrations/0033_detector_manufactured_date.py
new file mode 100644
index 0000000..5c68e33
--- /dev/null
+++ b/DOSPORTAL/migrations/0033_detector_manufactured_date.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.7 on 2023-12-03 17:23
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('DOSPORTAL', '0032_detector_data_alter_detectorlogbook_public_and_more'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='detector',
+ name='manufactured_date',
+ field=models.DateField(blank=True, help_text='Date when detector was manufactured', null=True, verbose_name='Manufactured date'),
+ ),
+ ]
diff --git a/DOSPORTAL/migrations/0034_record_metadata_alter_detector_data.py b/DOSPORTAL/migrations/0034_record_metadata_alter_detector_data.py
new file mode 100644
index 0000000..787539a
--- /dev/null
+++ b/DOSPORTAL/migrations/0034_record_metadata_alter_detector_data.py
@@ -0,0 +1,23 @@
+# Generated by Django 4.2.7 on 2023-12-03 20:03
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('DOSPORTAL', '0033_detector_manufactured_date'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='record',
+ name='metadata',
+ field=models.JSONField(help_text='record metadata, used for advanced data processing and maintaining', null=True, verbose_name='record_metadata'),
+ ),
+ migrations.AlterField(
+ model_name='detector',
+ name='data',
+ field=models.JSONField(help_text='Detector metadata, used for advanced data processing and maintaining', verbose_name='Detector metadata'),
+ ),
+ ]
diff --git a/DOSPORTAL/migrations/0035_remove_record_time_end_record_record_duration.py b/DOSPORTAL/migrations/0035_remove_record_time_end_record_record_duration.py
new file mode 100644
index 0000000..f4f5a1f
--- /dev/null
+++ b/DOSPORTAL/migrations/0035_remove_record_time_end_record_record_duration.py
@@ -0,0 +1,22 @@
+# Generated by Django 4.2.7 on 2023-12-03 21:17
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('DOSPORTAL', '0034_record_metadata_alter_detector_data'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='record',
+ name='time_end',
+ ),
+ migrations.AddField(
+ model_name='record',
+ name='record_duration',
+ field=models.DurationField(help_text='Duration of record', null=True, verbose_name='Record duration'),
+ ),
+ ]
diff --git a/DOSPORTAL/models.py b/DOSPORTAL/models.py
index 3aec06d..21be6df 100644
--- a/DOSPORTAL/models.py
+++ b/DOSPORTAL/models.py
@@ -191,8 +191,19 @@ class Detector(UUIDMixin):
related_name="detectors"
)
+ manufactured_date = models.DateField(
+ _("Manufactured date"),
+ help_text=_("Date when detector was manufactured"),
+ null=True, blank=True
+ )
+
+ data = models.JSONField(
+ _("Detector metadata"),
+ help_text="Detector metadata, used for advanced data processing and maintaining"
+ )
+
def __str__(self) -> str:
- return "Detector {} ({})".format(self.name, self.type.manufacturer.name)
+ return "Detector {} ({}), SN:{}".format(self.name, self.type.manufacturer.name, self.sn)
class DetectorLogbook(UUIDMixin):
@@ -210,8 +221,13 @@ class DetectorLogbook(UUIDMixin):
created = models.DateTimeField(auto_now_add=True)
text = models.TextField(
- _("Description zásahu")
+ _("Logbook text"),
+ help_text="Detailed description of activity made on the detector."
)
+ public = models.BooleanField(
+ _("Wish to be visible to everyone?"),
+ help_text=_("Private logbook will be visible for maintainers of detector and for dosportal admins."),
+ default=True)
class measurement_campaign(UUIDMixin):
@@ -342,9 +358,6 @@ class record(UUIDMixin):
)
def user_directory_path(instance, filename):
- # return "data/user_records/{0}/{1}".format(instance.user.id, filename)
- print(".....")
- print(instance.measurement.author.pk)
return "data/user_records/log_{1}".format(instance.measurement.author.pk, instance.pk)
log_file = models.FileField(
@@ -361,9 +374,11 @@ def user_directory_path(instance, filename):
null=True,
)
- time_end = models.DateTimeField(
- verbose_name = _("Measurement beginning time"),
- null=True,
+
+ record_duration = models.DurationField(
+ verbose_name = _("Record duration"),
+ help_text=_("Duration of record"),
+ null=True
)
@@ -380,6 +395,12 @@ def user_directory_path(instance, filename):
help_text=_("Type of log file")
)
+ metadata = models.JSONField(
+ _("record_metadata"),
+ help_text=_("record metadata, used for advanced data processing and maintaining"),
+ null=True
+ )
+
def __str__(self) -> str:
return "record ({}, {}, start {}, {})".format( get_enum_dsc(self.RECORD_TYPES, self.record_type), self.id, self.time_start, 0)
diff --git a/DOSPORTAL/settings.py b/DOSPORTAL/settings.py
index 1dbd810..9742adc 100644
--- a/DOSPORTAL/settings.py
+++ b/DOSPORTAL/settings.py
@@ -38,14 +38,17 @@
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
+ 'django.contrib.postgres',
'bootstrap5',
#'background_task',
+ 'django_json_widget',
'rest_framework',
'corsheaders',
'jquery',
'import_export',
'django_select2',
'martor',
+ 'django_tables2',
'DOSPORTAL',
'django_q',
diff --git a/DOSPORTAL/templates/detectors/detectors_detail.html b/DOSPORTAL/templates/detectors/detectors_detail.html
index ff03ab0..406b43c 100644
--- a/DOSPORTAL/templates/detectors/detectors_detail.html
+++ b/DOSPORTAL/templates/detectors/detectors_detail.html
@@ -3,22 +3,58 @@
{% extends "base.html" %}
{% block content %}
- Detektor: {{ detector.name }} {% if user.is_authenticated %} {%endif%}
-
DOSPORTAL ID: {{ detector.id }}
- Serial number: {{ detector.sn }}
- Type: {{ detector.type }}
-
-Měření s tímto detektorem:
+
+
+
+
+ {% if detector.description %}
+
+ {{detector.description }}
+
+ {%endif%}
+
Serial number: {{ detector.sn }}
+ Type: {{ detector.type }}
+ Advanced metadata:
+
{{detector.data}}
+
Measurements conducted with this detector:
+
+
+ Records created with this detector:
+
+
+
+
+
+
+
+
+
+
-
-Servisní záznamy:
+Servisní záznamy:
{% for logbook in detector.logbook.all %}
@@ -33,5 +69,29 @@
Servisní záznamy:
{%endfor%}
+{% if not detector.logbook.all %}
+
+
+ No log in logbook of this detector.
+
+{%endif%}
+
+
+
{% endblock %}
diff --git a/DOSPORTAL/templates/detectors/detectors_overview.html b/DOSPORTAL/templates/detectors/detectors_overview.html
new file mode 100644
index 0000000..54b7868
--- /dev/null
+++ b/DOSPORTAL/templates/detectors/detectors_overview.html
@@ -0,0 +1,38 @@
+{% extends "base.html" %}
+{% load martortags %}
+
+{% block content %}
+
+Detectors DOSPORTAL database
+{% if detector_list %}
+
+
+
+ # |
+ Name |
+ Type |
+ SerialNumber |
+ Popis |
+ Records |
+
+
+
+ {% for detector in detector_list.reverse %}
+
+ {{ forloop.counter }} |
+ {{ detector.name }} |
+ {{ detector.type }} |
+ {{detector.sn}} |
+ {{detector.description | safe_markdown }} |
+ {{detector.records.count }} |
+
+
+ {% endfor %}
+
+
+{% else %}
+ There are no detector in database.
+{% endif %}
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/DOSPORTAL/templates/measurements/measurement_detail.html b/DOSPORTAL/templates/measurements/measurement_detail.html
index 170598a..660f5f6 100644
--- a/DOSPORTAL/templates/measurements/measurement_detail.html
+++ b/DOSPORTAL/templates/measurements/measurement_detail.html
@@ -4,10 +4,18 @@
{% block content %}
+
+
+
{%endif%}
- - Autor: {{ measurement.author }}
-
- Type: {{ measurement.measurement_type }}
-
- Zacatek: {{ measurement.time_start }}
-
- Konec: {{ measurement.time_konec }}
-
- Let: {{ measurement.flight }} {% if user.is_authenticated %} {%endif%}
-
- Zaznamy:
+
- Author: {{ measurement.author }}
+
- Log type: {{ measurement.measurement_type }}
+
- Beginning: {{ measurement.time_start }}
+
- Ending: {{ measurement.time_konec }}
+
- Flight: {{ measurement.flight }} {% if user.is_authenticated %} {%endif%}
+
- Records:
@@ -77,9 +85,55 @@ NOT INITIALIZED
+
+
diff --git a/DOSPORTAL/templates/records/record_detail.html b/DOSPORTAL/templates/records/record_detail.html
new file mode 100644
index 0000000..25370c4
--- /dev/null
+++ b/DOSPORTAL/templates/records/record_detail.html
@@ -0,0 +1,45 @@
+
+
+{% extends "base.html" %}
+
+{% block content %}
+
+
+
+
+
+
+
+
+ - Detector: {{ record.detector }}
+
- Record start time: {{ record.time_start }}
+
- Record duration: {{ record.record_duration }}
+ - Type: {{ record.record_type }}
+
- Advanced metadata:
+ {{record.metadata }}
+ - Description: {{record.description}}
+
- File size: {{record.log_file.size}}
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
diff --git a/DOSPORTAL/templates/user/user_profile.html b/DOSPORTAL/templates/user/user_profile.html
new file mode 100644
index 0000000..109d6e6
--- /dev/null
+++ b/DOSPORTAL/templates/user/user_profile.html
@@ -0,0 +1,24 @@
+
+{% extends "base.html" %}
+{% load martortags %}
+
+{% block content %}
+
+Username: {{ user.username }} {% if user.is_authenticated %} {%endif%}
+Email: {{ user.email }}
+First Name: {{ user.first_name }}
+Last Name: {{ user.last_name }}
+
+
+
+
+
+Maintainer of detectors:
+
+TODO:
+
+Author of measurements
+
+TODO:
+
+{% endblock %}
diff --git a/DOSPORTAL/urls.py b/DOSPORTAL/urls.py
index 242ad01..16f7aea 100644
--- a/DOSPORTAL/urls.py
+++ b/DOSPORTAL/urls.py
@@ -20,26 +20,37 @@
from django.views.generic.base import TemplateView
import uuid
-from .views import MeasurementsListView, MeasurementDetailView, MeasurementNewView, RecordNewView, MeasurementDataView, measuredDataGet, measuredSpectraGet
-from .views_detectors import DetectorView
+from .views import MeasurementsListView, MeasurementDetailView, MeasurementNewView, RecordNewView, MeasurementDataView, measuredDataGet, measuredSpectraGet, user_profile
+from .views_detectors import DetectorView, DetectorOverview, DetectorNewLogbookRecord
from .views_flights import FlightView
+from .views_record import RecordView, GetSpectrum, GetEvolution
urlpatterns = [
path('admin/', admin.site.urls),
path("accounts/", include("django.contrib.auth.urls")),
+ path('user/', user_profile, name='my_user_profile'),
+ path('user/', user_profile, name='user_profile'),
+
path("measurements/", MeasurementsListView.as_view(), name="measurements"),
path("measurement/new/", MeasurementNewView, name='measurement-new'),
path('measurement//record/new/', RecordNewView, name="record-upload"),
path('measurement//visualizate/', MeasurementDataView, name="measurement-data-view"),
# path('measurement//metadata/', MeasurementDataView, name="measurement-data-view"),
path('measurement//measured_data/', measuredDataGet, name="measurement-data-get"),
+ path('measurement//measured_evolution/', measuredDataGet, name="measurement-evolution-get"),
path('measurement//measured_spectra/', measuredSpectraGet, name="measurement-spectra-get"),
path('measurement//', MeasurementDetailView, name='measurement-detail'),
+ path('record//', RecordView, name='record-view'),
+ path('record//get_spectrum/', GetSpectrum, name='record-GetSpectrum'),
+ path('record//get_evolution/', GetEvolution, name='record-GetEvolution'),
+
path('flight//', FlightView, name='flight-detail'),
+ path('detector//new_logbook_record', DetectorNewLogbookRecord),
+ path('detectors/', DetectorOverview.as_view(), name="detector-overview"),
path('detector//', DetectorView, name="detector-view"),
path("select2/", include("django_select2.urls")),
diff --git a/DOSPORTAL/views.py b/DOSPORTAL/views.py
index a951ef8..ff63080 100644
--- a/DOSPORTAL/views.py
+++ b/DOSPORTAL/views.py
@@ -5,6 +5,10 @@
record, Detector, DetectorType)
from django.shortcuts import get_object_or_404, redirect, render
+from django.contrib.auth.decorators import login_required
+from django.contrib.auth.models import User
+
+from .forms import RecordForm
from DOSPORTAL import models
@@ -44,26 +48,6 @@ def get_context_data(self, **kwargs):
return context
-class RecordForm(forms.ModelForm):
- log_file = forms.FileField(
- required=False,
- widget=forms.widgets.FileInput(),
- label="Log file"
- )
-
- time_start = forms.DateTimeField(
- widget=forms.DateTimeInput(attrs={
- 'type': "datetime-local",
- 'class': 'form-control datetimepicker-input',
- })
- )
-
- class Meta:
- model = record
- exclude = ("time_end", "measurement", "log_filename")
-
-
-
class NewMeasurementForm(forms.ModelForm):
name = forms.CharField(
@@ -93,27 +77,75 @@ def handle_uploaded_file(f, file):
destination.write(chunk)
+def obtain_parameters_from_log(file):
+ import os
+
+ f = open(file)
+ line_1 = f.readline().rstrip().split(',')
+ record_metadata = {}
+ record_metadata['detector'] = dict(zip(['DET', 'detector_type', 'firmware_build', 'channels', 'firmware_commit', 'firmware_origin', 'detector_sn'], line_1))
+
+ time_start = 0
+ stop_stop = 0
+ while True:
+ line = f.readline()
+ if line.startswith('$HIST'):
+ line = line.rstrip().split(',')
+ time_start = float(line[2])
+ break
+ i = -1
+ flen = len(f.readlines())
+ while True:
+ f.seek(flen+i)
+ line = f.readline()
+ if line.startswith('$HIST'):
+ line = line.rstrip().split(',')
+ time_stop = float(line[2])
+ count = int(line[1])
+ break
+ i -= 1
+
+ record_metadata['record'] = {}
+ record_metadata['record'] = {
+ 'duration': time_stop - time_start,
+ 'count': count
+ }
+
+
+ f.close()
+ return record_metadata
def RecordNewView(request, pk):
if request.method == "POST":
print("POST... s formulářem :) ")
form = RecordForm(request.POST, request.FILES)
- print(form)
+ #print(form)
+
if form.is_valid():
data = form.save(commit=False)
data.author = request.user
- data.log_file= request.FILES['log_file']
- data.log_filename = request.FILES['log_file'].name.split("/")[-1]
+ data.log_file = request.FILES['log_file']
+
+ #data.log_filename = request.FILES['log_file'].name.split("/")[-1]
+ handle_uploaded_file(request.FILES['log_file'], data.log_file.name)
+ metadata = obtain_parameters_from_log(data.log_file.path)
+ if metadata:
+ detector_pk = Detector.objects.get(sn=metadata['detector']['detector_sn'])
+ if detector_pk:
+ data.detector = detector_pk
+ data.metadata = metadata
+ data.record_duration = timedelta(seconds = metadata['record']['duration'])
data.measurement = measurement.objects.get(pk=pk)
- handle_uploaded_file(request.FILES["log_file"], data.log_file.name)
+
+ print(data)
data.save()
else:
print("Form není validni")
print(form.errors)
- return redirect("measurements")
+ return redirect("measurement-detail", pk=pk)
@@ -160,6 +192,12 @@ def MeasurementDataView(request, pk):
def measuredDataGet(request, pk):
+ from io import StringIO
+
+ response = HttpResponse(
+ content_type="text/csv",
+ #headers={"Content-Disposition": 'attachment; filename="data.csv"'},
+ )
series = []
a=measurement.objects.get(pk=pk)
@@ -167,131 +205,171 @@ def measuredDataGet(request, pk):
loc=record.objects.filter(measurement=pk, record_type="L")
- for i, b in enumerate(rec):
+ b = rec[0]
- l=[]
- l.extend(range(0,505))
-
- s = {
- 'name': "Evolution_"+str(i)+"_avg",
- 'type': 'line',
- 'data': [],
- 'showSymbol': False,
- #'xAxisIndex': 1,
- 'yAxisIndex': 1,
- }
-
-
- s2 = {
- 'name': "Evolution_"+str(i),
- 'type': 'scatter',
- 'data': [],
- 'symbolSize': 3,
- 'itemStyle': {
- 'opacity': 0.4
- },
- }
-
- df = pd.read_csv(b.log_file, sep=',', header=None, names=l, comment='*', low_memory=False)
- df = df.reset_index(drop=True)
+ #for i, b in enumerate(rec):
- LAST_CHANNEL = len(df. columns)
+ print(b.log_file, b.log_filename)
+ f = open(b.log_file.path )
+ log_info = f.readline()
+ f.close()
- df[2] = df[2].apply(pd.to_numeric, errors='coerce')
+ histogram = []
+ metadata = {}
- df['runtime'] = np.nan
- df.loc[df[0]=='$HIST','seconds'] = df.loc[df[0]=='$HIST',2]
- df.loc[df[0]=='$DOS','seconds'] = 0
- df['runtime'] = df['seconds'].diff() * -1
- df = df.copy()
+ with open(b.log_file.path) as f:
+ r = f.readline()
+ if r.startswith("$HIST"):
+ histogram.append(r)
+ elif r.startswith("$DOS"):
+ mdata = r.split(',')
+ dict(zip(['DET', 'detector_type', 'firmware_build', 'channels', 'firmware_commit', 'firmware_origin', 'detector_sn'], mdata))
- run = 0
- df['run'] = np.nan
- df['run'].fillna(method="ffill", inplace=True)
+
+ df = pd.read_csv(StringIO('\n'.join(histogram)), delimiter=',', low_memory=False)
+ print(df)
- df[2] = pd.to_numeric(df[2])
- df['time'] = b.time_start + pd.to_timedelta(df[2], unit='s')
- df.set_index(df['time'], drop=False, inplace=True)
+ # Parse log file header to obtain basic informations
- #cmap = matplotlib.cm.get_cmap('tab10')
- #color = cmap(i/len(rec))
-
- #df = data[x]['df']
- df['sum'] = df[range(FIRST_CHANNEL,LAST_CHANNEL)].sum(axis=1)/10/2
- #df['sum'] = df[range(FIRST_CHANNEL,LAST_CHANNEL)].sum(axis=1)
+ # s = {
+ # 'name': "Evolution_"+str(i)+"_avg",
+ # 'type': 'line',
+ # 'data': [],
+ # 'showSymbol': False,
+ # #'xAxisIndex': 1,
+ # 'yAxisIndex': 1,
+ # }
- df['sum_f'] = df['sum'].rolling(15).mean()
- sd = df['sum_f'].copy().dropna()
- s['data'] = list(zip(sd.index, sd))
+ # s2 = {
+ # 'name': "Evolution_"+str(i),
+ # 'type': 'scatter',
+ # 'data': [],
+ # 'symbolSize': 3,
+ # 'itemStyle': {
+ # 'opacity': 0.4
+ # },
+ # }
- sd2 = df['sum'].copy().dropna()
- s2['data'] = list(zip(sd2.index, sd2))
+ #df = pd.read_csv(b.log_file, sep=',', header=None, comment='*', low_memory=False, skiprows=1)
+ #df = df.reset_index(drop=True)
- print(s['data'])
- series.append(s)
- series.append(s2)
-
- for i, l in enumerate(loc):
- if 'gpx' in l.log_filename:
- print("Nacitam GPX..")
- print(l.log_file)
- gpx_file = open(str(l.log_file), 'r')
- gpx = gpxpy.parse(gpx_file)
-
- #df = pd.DataFrame(columns=['lon', 'lat', 'alt', 'time'])
- df = pd.DataFrame(columns=['lon', 'lat', 'alt', 'time'])
- for segment in gpx.tracks[0].segments:
- data = segment.points
- for point in data:
- df.loc[len(df)] = pd.Series({'lon': point.longitude, 'lat' : point.latitude, 'alt' : point.elevation, 'time' : point.time})
-
- df = df.sort_values(by='time')
- df.set_index(df['time'], drop=False, inplace=True)
- #df = df.reset_index()
-
- df = df.fillna(method='ffill')
- df = df.fillna(method='bfill')
-
- s = {
- 'name': "Altitude_"+str(i),
- 'type': 'line',
- 'data': list(zip(df.index, df['alt']*0.001)),
- 'symbolSize': 3,
- 'itemStyle': {
- 'opacity': 0.4
- },
- 'yAxisIndex': 1,
- }
-
- series.append(s)
+ l=[]
+ l.extend(range(0,2000))
+ df = pd.read_csv(b.log_file.path, sep=' ', header=None, names=l, comment='#', low_memory=False)#,engine='python' )
+ #df = pd.read_csv(b.log_file.path, header=None, comment='*', low_memory=False, skiprows=1)
+ #df = df[df[0].str.startswith("$HIST")]
+ #df = df[0].str.split(",", expand=True)
+
+
+
+
+ response.write(df.to_csv(index=False))
+ return response
+
+
+ # print("DF")
+
+ # LAST_CHANNEL = len(df.columns)
+ # #df.set_columns = list(range(0,LAST_CHANNEL))
+
+ # df[2] = df[2].apply(pd.to_numeric, errors='coerce')
+
+ # df['runtime'] = np.nan
+ # df.loc[df[0]=='$HIST','seconds'] = df.loc[df[0]=='$HIST',2]
+ # df.loc[df[0]=='$DOS','seconds'] = 0
+ # df['runtime'] = df['seconds'].diff() * -1
+ # df = df.copy()
+
+ # run = 0
+ # df['run'] = np.nan
+ # df['run'].fillna(method="ffill", inplace=True)
+
+ # df[2] = pd.to_numeric(df[2])
+ # df['time'] = b.time_start + pd.to_timedelta(df[2], unit='s')
+ # df.set_index(df['time'], drop=False, inplace=True)
+
+
+ # #cmap = matplotlib.cm.get_cmap('tab10')
+ # #color = cmap(i/len(rec))
+
+ # #df = data[x]['df']
+ # df['sum'] = df[range(FIRST_CHANNEL,LAST_CHANNEL)].sum(axis=1)/10/2
+ # #df['sum'] = df[range(FIRST_CHANNEL,LAST_CHANNEL)].sum(axis=1)
+
+ # df['sum_f'] = df['sum'].rolling(15).mean()
+
+ # sd = df['sum_f'].copy().dropna()
+ # s['data'] = list(zip(sd.index, sd))
+
+ # sd2 = df['sum'].copy().dropna()
+ # s2['data'] = list(zip(sd2.index, sd2))
+
+ # print(s['data'])
+
+ # series.append(s)
+ # series.append(s2)
+
+ # for i, l in enumerate(loc):
+ # if 'gpx' in l.log_filename:
+ # print("Nacitam GPX..")
+ # print(l.log_file)
+ # gpx_file = open(str(l.log_file), 'r')
+ # gpx = gpxpy.parse(gpx_file)
+
+ # #df = pd.DataFrame(columns=['lon', 'lat', 'alt', 'time'])
+ # df = pd.DataFrame(columns=['lon', 'lat', 'alt', 'time'])
+ # for segment in gpx.tracks[0].segments:
+ # data = segment.points
+ # for point in data:
+ # df.loc[len(df)] = pd.Series({'lon': point.longitude, 'lat' : point.latitude, 'alt' : point.elevation, 'time' : point.time})
+
+ # df = df.sort_values(by='time')
+ # df.set_index(df['time'], drop=False, inplace=True)
+ # #df = df.reset_index()
+
+ # df = df.fillna(method='ffill')
+ # df = df.fillna(method='bfill')
+
+ # s = {
+ # 'name': "Altitude_"+str(i),
+ # 'type': 'line',
+ # 'data': list(zip(df.index, df['alt']*0.001)),
+ # 'symbolSize': 3,
+ # 'itemStyle': {
+ # 'opacity': 0.4
+ # },
+ # 'yAxisIndex': 1,
+ # }
+
+ # series.append(s)
- elif '.csv' in l.log_filename:
- df = pd.read_csv(l.log_file)
- df['UTC'] = pd.to_datetime(df['UTC'])
- df = df.sort_values(by='UTC')
- df.set_index(df['UTC'], drop=True, inplace=True)
+ # elif '.csv' in l.log_filename:
+ # df = pd.read_csv(l.log_file)
+ # df['UTC'] = pd.to_datetime(df['UTC'])
+ # df = df.sort_values(by='UTC')
+ # df.set_index(df['UTC'], drop=True, inplace=True)
- print(df)
+ # print(df)
- s = {
- 'name': "Altitude_"+str(i),
- 'type': 'line',
- 'data': list(zip(df.index, df['Altitude']*0.0003048)),
- 'symbolSize': 3,
- 'itemStyle': {
- 'opacity': 0.4
- },
- 'yAxisIndex': 1,
- }
+ # s = {
+ # 'name': "Altitude_"+str(i),
+ # 'type': 'line',
+ # 'data': list(zip(df.index, df['Altitude']*0.0003048)),
+ # 'symbolSize': 3,
+ # 'itemStyle': {
+ # 'opacity': 0.4
+ # },
+ # 'yAxisIndex': 1,
+ # }
- series.append(s)
+ # series.append(s)
- return JsonResponse(series, safe=False)
+ # return JsonResponse(series, safe=False)
def measuredSpectraGet(request, pk):
@@ -305,17 +383,17 @@ def measuredSpectraGet(request, pk):
rec=record.objects.filter(measurement=pk, record_type="S")
#loc=record.objects.filter(measurement=pk, record_type="L")
- l=[]
- l.extend(range(0,505))
+ #l=[]
+ #l.extend(range(0,2000))
spc = []
for i, b in enumerate(rec):
- df = pd.read_csv(b.log_file, sep=',', header=None, names=l, comment='*', low_memory=False)
+ df = pd.read_csv(b.log_file, sep=',', header=None, comment='*', low_memory=False, skiprows=2)
df = df.reset_index(drop=True)
- LAST_CHANNEL = len(df. columns)
+ LAST_CHANNEL = len(df.columns)
df[2] = df[2].apply(pd.to_numeric, errors='coerce')
@@ -371,4 +449,19 @@ def measurementGetData(request, pk):
a=measurement.objects.get(pk=pk)
rec=record.objects.filter(measurement=pk, record_type="S")
- loc=record.objects.filter(measurement=pk, record_type="L")
\ No newline at end of file
+ loc=record.objects.filter(measurement=pk, record_type="L")
+
+
+
+@login_required
+def user_profile(request, username = None):
+ if username is None:
+ return redirect('user_profile', username=request.user.username)
+
+ user = get_object_or_404(User, username = username)
+ #user = request.user
+ context = {
+ 'user': user
+ }
+
+ return render(request, 'user/user_profile.html', context)
\ No newline at end of file
diff --git a/DOSPORTAL/views_detectors.py b/DOSPORTAL/views_detectors.py
index 7fac61c..81627f1 100644
--- a/DOSPORTAL/views_detectors.py
+++ b/DOSPORTAL/views_detectors.py
@@ -2,12 +2,15 @@
from django.http import HttpResponse, JsonResponse
from django.views import generic
from .models import (DetectorManufacturer, measurement,
- record, Detector, DetectorType)
+ record, Detector, DetectorType, DetectorLogbook)
+from .forms import DetectorLogblogForm
from django.shortcuts import get_object_or_404, redirect, render
from DOSPORTAL import models
+from django.views import generic
+from django.views.generic import ListView
FIRST_CHANNEL = 10
@@ -16,5 +19,48 @@
def DetectorView(request, pk):
detector = Detector.objects.get(pk=pk)
#return HttpResponse(a)
- return render(request, 'detectors/detectors_detail.html', context={'detector': detector })
+ return render(request, 'detectors/detectors_detail.html', context={'detector': detector, 'DetectorLogblogForm': DetectorLogblogForm})
+
+
+
+class DetectorOverview(generic.ListView):
+ #detectors = DetectorsTable()
+ model = Detector
+ context_object_name = "detector_list"
+ sequence = ("id", "sn", "name", )
+ queryset = Detector.objects.all()
+ template_name = 'detectors/detectors_overview.html'
+
+ # def get_context_data(self, **kwargs):
+ # context = super(DetectorOverview, self).get_context_data(**kwargs)
+ # context['some_data'] = 'This is just some data'
+ # return context
+
+
+ def POST(self, request, *args, **kwargs):
+ # Tato část se zavolá při POST požadavku
+ print("POST")
+ print(request)
+ form = DetectorLogblogForm(request.POST) # Nahraďte 'YourForm' za skutečný název vašeho formuláře
+ if form.is_valid():
+
+ text = form.cleaned_data['text']
+ DetectorLogbook.objects.create(detector=detector, author=request.user, text=text)
+
+ return redirect('detector-view')
+
+
+ return render(request, self.template_name, {'form': form, 'detector_list': self.get_queryset()})
+
+def DetectorNewLogbookRecord(request, pk):
+ detector = Detector.objects.get(pk=pk)
+
+ form = DetectorLogblogForm(request.POST) # Nahraďte 'YourForm' za skutečný název vašeho formuláře
+ if form.is_valid():
+
+ text = form.cleaned_data['text']
+ DetectorLogbook.objects.create(detector=detector, author=request.user, text=text)
+
+ return redirect('detector-view', pk=pk)
+ #return HttpResponse(a)
diff --git a/DOSPORTAL/views_record.py b/DOSPORTAL/views_record.py
new file mode 100644
index 0000000..c12b4af
--- /dev/null
+++ b/DOSPORTAL/views_record.py
@@ -0,0 +1,36 @@
+from django import forms
+from django.http import HttpResponse, JsonResponse
+from django.views import generic
+from .models import (DetectorManufacturer, measurement,
+ record, Detector, DetectorType, DetectorLogbook)
+from .forms import DetectorLogblogForm
+
+from django.shortcuts import get_object_or_404, redirect, render
+
+from DOSPORTAL import models
+
+from django.views import generic
+from django.views.generic import ListView
+
+
+FIRST_CHANNEL = 10
+
+
+def RecordView(request, pk):
+ rec = record.objects.get(pk=pk)
+ return render(request, 'records/record_detail.html', context={'record': rec})
+
+
+def GetSpectrum(request, pk):
+
+ record_o = record.objects.filter(pk=pk)
+ print(record_o)
+ pass
+
+
+
+def GetEvolution(request, pk):
+
+ record_o = record.objects.filter(pk=pk)
+ print(record_o)
+ pass
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index a31f7d6..9a91fbc 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -3,8 +3,8 @@ FROM debian:latest
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
-RUN apt update
-RUN apt install -y python3 net-tools python3-pip libpq-dev redis
+RUN apt-get update
+RUN apt-get install -y python3 net-tools python3-pip libpq-dev redis
WORKDIR /DOSPORTAL
COPY requirements.txt /DOSPORTAL/
diff --git a/docker-compose.yml b/docker-compose.yml
index 557fd37..ff142b7 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -5,12 +5,16 @@ networks:
config:
- subnet: 10.5.0.0/16
gateway: 10.5.0.1
+ default:
+ driver: bridge
+ ipam:
+ driver: default
services:
- db:
+ db_dosportal:
image: postgres
volumes:
- - ./data/db:/var/lib/postgresql/data
+ - ./data/dosportal/db:/var/lib/postgresql/data
environment:
- POSTGRES_DB=dosportal
- POSTGRES_USER=dosportal_user
@@ -20,19 +24,22 @@ services:
ipv4_address: 10.5.0.5
web:
- build: .
+ build:
+ context: .
+ network: host
# platform: linux/amd64
# command: python manage.py runserver 0.0.0.0:8000
# entrypoint: python3 manage.py runserver 0.0.0.0:8000
volumes:
- .:/DOSPORTAL
ports:
- - "8000:8000"
+ - "8100:8000"
depends_on:
- - db
+ - db_dosportal
networks:
inet:
ipv4_address: 10.5.0.6
+# default:
# redis:
diff --git a/requirements.txt b/requirements.txt
index 6079716..0aaf175 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -10,6 +10,8 @@ django-jquery
django-import-export
django-select2
djangorestframework
+django-json-widget
+django-tables2
martor
markdown
django-filter