<commit_before># Copyright 2016 the Queen's University Biological Station

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


from django.db import models
from django.contrib.postgres.fields import ArrayField, DateTimeRangeField


class DataType(models.Model):
    """
    A model of reading's data type. There may be multiple sensors which share a single data type; for example,
    temperature.
    """

    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    name = models.CharField(max_length=100)
    short_name = models.CharField(max_length=20, db_index=True)  # For downloaded data, the full name would be unwieldy

    unit = models.CharField(max_length=40)  # Example: celcius.

    def __repr__(self):
        return "<DataType {} ({})>".format(self.name, self.short_name)

    def __str__(self):
        return self.name


class Sensor(models.Model):
    """
    A model of a specific class of sensor attached to various stations. Many stations share similar sensors. This model 
    is used to keep track of data format, since sensors may return different formats for the same data type.
    
    A data type for the sensor to refer to should exist before sensor creation. The foreign key is nullable for
    backwards compatibility reasons.
    """

    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    name = models.CharField(max_length=100)
    data_id = models.CharField(max_length=20)  # DEPRECATED

    decimals = models.PositiveSmallIntegerField()  # Data points are sent without decimals; they need to be adjusted.

    def __repr__(self):
        return "<Sensor {}>".format(self.name)

    def __str__(self):
        return self.name


class Station(models.Model):
    """
    A model representing a climate station. Climate stations are effectively a list of sensors with an attached GOES ID.
    """

    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    name = models.CharField(max_length=100)
    goes_id = models.CharField(max_length=8)

    # Foreign keys
    sensors = models.ManyToManyField(Sensor, through="StationSensorLink", related_name="stations")

    def __repr__(self):
        return "<Station {} | GOES ID: {}>".format(self.name, self.goes_id)

    def __str__(self):
        return self.name


class StationSensorLink(models.Model):
    """
    A model representing many-to-many links between stations and common sensor classes.
    """

    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    station_order = models.PositiveSmallIntegerField()  # Need to keep an order for sensors to parse message data.
    read_frequency = models.PositiveSmallIntegerField(default=4)  # Default to 4 times per message.

    # Foreign Keys
    station = models.ForeignKey(Station, on_delete=models.CASCADE)
    sensor = models.ForeignKey(Sensor, on_delete=models.CASCADE)
    data_type = models.ForeignKey(DataType, null=True, on_delete=models.SET_NULL)

    def __repr__(self):
        return "<Link | Station: {}, Sensor: {}>".format(self.station, self.sensor)

    def __str__(self):
        return "Link between station {} and sensor {}".format(self.station, self.sensor)

    class Meta:
        ordering = ("station_order",)


class Reading(models.Model):
    """
    A model representing an individual point of data from a specific station, sensor, and with a specific read time.
    """

    FROM_GOES = "G"
    FROM_DEVICE_LOG = "L"

    DATA_SOURCE_CHOICES = (
        (FROM_GOES, "GOES satellite message"),
        (FROM_DEVICE_LOG, "Station data log"),
    )

    def decimal_value(self):
        return self.value / (10 ** self.sensor.decimals)
<commit_msg>Add human-readable name for station-sensor links.<commit_after># Copyright 2016 the Queen's University Biological Station

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


from django.db import models
from django.contrib.postgres.fields import ArrayField, DateTimeRangeField


class DataType(models.Model):
    """
    A model of reading's data type. There may be multiple sensors which share a single data type; for example,
    temperature.
    """

    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    name = models.CharField(max_length=100)
    short_name = models.CharField(max_length=20, db_index=True)  # For downloaded data, the full name would be unwieldy

    unit = models.CharField(max_length=40)  # Example: celcius.

    def __repr__(self):
        return "<DataType {} ({})>".format(self.name, self.short_name)

    def __str__(self):
        return self.name


class Sensor(models.Model):
    """
    A model of a specific class of sensor attached to various stations. Many stations share similar sensors. This model 
    is used to keep track of data format, since sensors may return different formats for the same data type.
    
    A data type for the sensor to refer to should exist before sensor creation. The foreign key is nullable for
    backwards compatibility reasons.
    """

    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    name = models.CharField(max_length=100)
    data_id = models.CharField(max_length=20)  # DEPRECATED

    decimals = models.PositiveSmallIntegerField()  # Data points are sent without decimals; they need to be adjusted.

    def __repr__(self):
        return "<Sensor {}>".format(self.name)

    def __str__(self):
        return self.name


class Station(models.Model):
    """
    A model representing a climate station. Climate stations are effectively a list of sensors with an attached GOES ID.
    """

    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    name = models.CharField(max_length=100)
    goes_id = models.CharField(max_length=8)

    # Foreign keys
    sensors = models.ManyToManyField(Sensor, through="StationSensorLink", related_name="stations")

    def __repr__(self):
        return "<Station {} | GOES ID: {}>".format(self.name, self.goes_id)

    def __str__(self):
        return self.name


class StationSensorLink(models.Model):
    """
    A model representing many-to-many links between stations and common sensor classes.
    """

    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    station_order = models.PositiveSmallIntegerField()  # Need to keep an order for sensors to parse message data.
    read_frequency = models.PositiveSmallIntegerField(default=4)  # Default to 4 times per message.

    # Foreign Keys
    station = models.ForeignKey(Station, on_delete=models.CASCADE)
    sensor = models.ForeignKey(Sensor, on_delete=models.CASCADE)
    data_type = models.ForeignKey(DataType, null=True, on_delete=models.SET_NULL)

    def __repr__(self):
        return "<Link | Station: {}, Sensor: {}>".format(self.station, self.sensor)

    def __str__(self):
        return "Link between station {} and sensor {}".format(self.station, self.sensor)

    class Meta:
        ordering = ("station_order",)
        verbose_name = "station-sensor link"


class Reading(models.Model):
    """
    A model representing an individual point of data from a specific station, sensor, and with a specific read time.
    """

    FROM_GOES = "G"
    FROM_DEVICE_LOG = "L"

    DATA_SOURCE_CHOICES = (
        (FROM_GOES, "GOES satellite message"),
        (FROM_DEVICE_LOG, "Station data log"),
    )

    def decimal_value(self):
        return self.value / (10 ** self.sensor.decimals)

{'fraction_non_alphanumeric': 0.09053261244679628, 'fraction_numerical': 0.0064419647992637755, 'mean_word_length': 3.6293929712460065, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7210971', 'n_tokens_mistral': 2500, 'n_tokens_neox': 2401, 'n_words': 812}