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:

+ +
+
+ Detector: {{detector.name}} + {{detector.id}} + {% if user.is_authenticated %} + + {%endif%} + +
+
+ {% 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: +
      + {%for record in detector.records.all %} +
    • {{ record.id }} + {%endfor%} +
    + +
  • +
    + + + + + + -
    -

    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 %} + + +{%endif%} + + +
    +
    + + +
    +
    +
    + {% csrf_token %} + {{ DetectorLogblogForm.as_p }} + +
    + +
    +
    {% 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 %} + + + + + + + + + + + + + {% for detector in detector_list.reverse %} + + + + + + + + + + {% endfor %} + +
    #NameTypeSerialNumberPopisRecords
    {{ forloop.counter }}{{ detector.name }}{{ detector.type }}{{detector.sn}}
    {{detector.description | safe_markdown }}
    {{detector.records.count }}
    +{% 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 %} + + +
    - Měření: {{measurement.name}} + Measurement: {{measurement.name}} {{measurement.id}} {% if user.is_authenticated %} @@ -21,15 +29,15 @@
    {%endif%}
    @@ -77,9 +85,55 @@

    NOT INITIALIZED

    +
    +

    Graphs:

    +
    +
    +
    + + +
    + + +
    + 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 %} + + + +
    +
    + Record: {{record.id}} + + {% if user.is_authenticated %} + + {%endif%} + +
    +
    + + +
    +
    + + + + + + + +{% 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