公民科学领域的ERAV数据模型的参考实现。ERAV是EAV的扩展,支持为实体维护多方面的来源元数据。
项目描述
vera 是实体-记录-属性-值(ERAV)数据模型的参考实现。ERAV是EAV的扩展,增加了为实体维护多方面来源元数据的支持 [1]。
vera提供的ERAV实现优化了存储和跟踪在异构技术平台之间交换的时间序列数据的变化(例如,移动设备、Excel电子表格和第三方数据库)。在这种情况下,ERAV可以解释为事件-报告-属性-值,因为它代表了一系列由各种贡献者在例如环境监测或公民科学项目中提交的报告描述的事件。
入门
# Recommended: create virtual environment
# python3 -m venv venv
# . venv/bin/activate
pip install vera
vera是wq框架的扩展。有关问题报告,请参阅 https://github.com/wq/vera。
模型
vera的核心是一系列描述ERAV数据模型各种组件的 Django模型。
vera模型
有四个主要模型(ERAV)和三个辅助模型,共计七个模型。以下是从vera模型到其ERAV概念等价物的映射
ERAV等价物 |
模型 |
模块 |
---|---|---|
站点 |
vera.params |
|
实体 |
``事件`` |
vera.series |
报告状态 |
vera.params |
|
记录 |
``报告`` |
vera.series |
属性 |
``参数`` |
vera.params |
值 |
``结果`` |
vera.results |
事件结果 |
vera.results |
所有的 vera 模型都是可交换的,这意味着它们可以被继承和扩展而不会破坏 ERAV 模型所需的外键关系。基础模型在 vera 中实际上被分为三个模块,但都可以从 vera.base_models 中导入。例如,要自定义 Event 模型,可以继承 BaseEvent 并更新你的 settings.py
# myapp/models.py
from django.db import models
from vera.base_models import BaseEvent
class Event(BaseEvent):
date = models.DateTimeField()
type = models.CharField()
# settings.py
WQ_EVENT_MODEL = "myapp.Event"
注意,与任何可交换模型一样,Django 迁移不期望在初始迁移之后更改可交换设置。因此,一旦数据库中有数据,最好保持这些设置不变。
下面将详细描述这七个模型。
站点
Site 模型表示事件发生的位置。它并不是原始 ERAV 定义的一部分,但是一个自然的扩展。在默认实现中,Site 是一个具有 latitude 和 longitude 字段的 IdentifiedModel。
# myapp/models.py
from django.db import models
from vera.base_models import BaseSite
class Site(BaseSite):
description = models.TextField()
# settings.py
WQ_SITE_MODEL = "myapp.Site"
所有站点实例都有一个 valid_events 属性,它返回包含至少一个有效报告的所有事件实例。
事件
Event 模型对应于 ERAV 数据模型中的 实体。Event 代表监控事件的时序。例如,志愿者对观察站点的每次访问可以称为一个 Event。Event 模型不包含任何关于描述事件的数字记录的元数据。这些信息在下面的 Report 模型中。
至少,一个 Event 实例有一个 site 引用(见下文)和一个事件 date,这可能是一个日期或完整的日期和时间,具体取决于项目需求。默认实现假定一个没有时间的日期。可以通过扩展 BaseEvent 并通过 WQ_EVENT_MODEL 设置替换 Event 来配置自定义 date 字段和额外的属性。注意,如果替换了 Event,也应该替换 EventResult。
报告状态
为了支持自定义工作流程,报告状态的列表被维护为一个单独的模型,ReportStatus。ReportStatus 通过一个表示是否有该状态的报告应该被认为是有效的的 is_valid 布尔值扩展了 IdentifiedModel。可以通过扩展 BaseReportStatus 并通过 WQ_REPORTSTATUS_MODEL 设置替换 ReportStatus 来添加额外的属性。
在典型项目中,ReportStatus 模型可能包含以下实例
slug |
name |
is_valid |
---|---|---|
unverified |
未验证 |
False |
verified |
已验证 |
True |
deleted |
已删除 |
False |
报告
Report 模型对应于 ERAV 数据模型中的 记录。Report 跟踪关于 Event 的来源元数据,例如谁输入了它,何时输入等。根据数据输入的时间和方式,可能有多个 Reports 描述相同的事件。这些报告的状态是分开跟踪的。
至少,报告实例具有一个事件属性,一个状态属性(见下文),一个用户属性,以及一个进入时间戳。当通过REST API创建报告时,用户和进入将自动设置。可以通过扩展BaseReport并通过WQ_REPORT_MODEL设置替换报告来添加更多属性。请注意,报告模型仅包含溯源元数据,不包含有关事件本身的信息——事件模型应包含该信息。
除了默认管理器(objects)之外,报告还有一个自定义管理器valid_objects,它仅包括具有有效状态的报告。报告实例具有一个vals属性,可以用来检索(并设置)参数名称到结果值的映射字典(见下文)。
在存在多个有效报告的事件的情况下,如果报告包含相互矛盾的数据,则可能会有歧义。在这种情况下,可以使用WQ_VALID_REPORT_ORDER设置来控制哪些报告具有优先权。默认设置是("-entered", ),这给最近进入的报告以优先权。(参见CSCW论文,其中对冲突报告进行了深入讨论)。
参数
参数模型对应于ERAV数据模型中的属性。参数管理着项目跟踪的数据“属性”(或“特征”,或“字段”)的定义。通过将这些定义保存在单独的表中,项目可以适应新的任务定义,而无需开发人员向数据库添加列。
BaseParameter通过添加is_numeric布尔值和一个units定义(这通常仅适用于数值参数)扩展了IdentifiedModel。可以通过扩展BaseParameter并通过WQ_PARAMETER_MODEL设置替换参数来添加更多属性。
结果
结果模型对应于ERAV数据模型中的值。结果管理着项目跟踪的数据属性(或特征,或字段)的定义。结果是一个多对多的关系,将报告和参数与一个值链接起来:例如,“报告 #123 的温度值为15”。请注意,结果没有直接指向事件的外键——这是ERAV模型的核心区别。
至少,结果实例有一个type(它引用参数),一个报告,以及value_text和value_numeric字段——通常只有一个在给定的结果中设置,这取决于参数的is_numeric属性。结果实例还包含一个empty属性,以便在分析期间进行快速过滤(见下文)。可以通过扩展BaseResult并通过WQ_RESULT_MODEL设置替换结果来添加更多属性和自定义行为。请注意,如果替换了结果,则也应替换EventResult。
结果 实例具有一个可设置的 value 属性,该属性内部根据 参数 的不同映射到 value_text 或 value_numeric 属性。此外,结果 实例还包含一个 is_empty(val) 方法,用于设置 empty 属性。默认实现将 None、空字符串和仅包含空白字符的字符串视为空。
事件结果
EventResult 模型是一个 反规范化 表,包含所有有效事件的“活动”结果数据。一个有效事件是指至少有一个报告具有有效 ReportStatus 的报告。为了确定哪些结果是活动的
首先,从每个事件的所有有效报告中收集所有结果。仅包含非空结果。
接下来,结果按参数分组。每个参数只能有一个活动结果。
在每个参数组内部,结果根据 Report 排序,使用 WQ_VALID_REPORT_ORDER 设置。每个组中的第一个结果是该组的“活动”结果。
(这并不是算法的精确实现方式,但可以提供一个工作原理的概念)
在简单情况下,如果一个事件只有一个有效的 Report,那么该 Report 中所有的 Result 实例都将被计数为活动状态。在更复杂的情况下,一些 Result 实例可能被遮挡。
由于此算法可能计算成本较高,因此结果存储在 EventResult 模型中以便快速检索。不应直接修改 EventResult 模型,因为它会在每次 Event、Report 或 Result 更新时自动更新。
EventResult 模型包含一个 event 属性、一个 result 属性,以及来自 Event 和 Result 的所有字段(使用源模型名称作为前缀)。默认 EventResult 模型的完整字段集包括 event、result、event_site、event_date、result_type、result_report、result_value_numeric、result_value_text 和 result_empty。
每当 Event 或 Result 被替换时,也应替换 EventResult。可以使用 create_eventresult_model() 函数生成 EventResult 类,而无需手动复制所有字段定义。
# myapp/models.py
from django.db import models
from vera.base_models import BaseEvent, Result
class Event(BaseEvent):
date = models.DateTimeField()
type = models.CharField()
EventResult = create_eventresult_model(Event, Result)
# settings.py
WQ_EVENT_MODEL = "myapp.Event"
WQ_EVENTRESULT_MODEL = "myapp.EventResult"
数据管理
数据录入
vera是为与wq框架一起使用而设计的,该框架可以自动为站点、参数、报告状态和报告模型生成具有离线功能的表单。事件(Event)、结果(Result)和事件结果(EventResult)模型不应直接编辑,因为它们在提交报告表单时填充。默认的report_edit模板可以定制以获得更紧凑的布局。例如,请参阅Try WQ report_edit模板和wqxwq report_edit模板。
批量数据导入
vera内置了对通过Django数据向导从Excel和其他电子表格格式导入数据的支持。提供了四个默认向导模板(序列化器),如下截图所示。
序列化器选择:站点元数据、参数元数据、报告系列和结果系列
报告系列和结果系列序列化器都用于导入时间序列数据(同时填充事件、报告和结果表)。报告系列与结果系列之间的区别在于,前者假定参数名称作为电子表格顶部的列列出(如下面的截图所示),而后者假定每一行列出单个参数和一个结果。
报告系列列映射
批量导出和交互式图表
vera还附带了一个EventResultSerializer和视图,它们利用Django REST Pandas的图表序列化器。这使得通过wq/chartapp.js或底层模块(wq/chart.js和wq/pandas.js)快速从EventResult表生成d3.js图表成为可能。提供的TimeSeriesView、ScatterView和BoxPlotView实现了URL过滤identify,这意味着您可以通过向URL添加额外的slug来根据站点和/或参数进行筛选。
例如,以下URL配置
# myproject/urls.py
from vera.results.views import TimeSeriesView
urlpatterns = [
url(r'^data/(?P<ids>[^\.]+)/timeseries$', cls.as_view())
]
以下请求是可能的
URL路径 |
输出 |
---|---|
/data/stream1/temp /timeseries |
HTML表格和交互式wq/chartapp.js图表显示站点"stream1"的参数"temp"的事件结果值 |
/data/stream1/temp /timeseries.csv |
相同的CSV导出 |
/data/stream1/lake2/timeseries.csv |
从站点"stream1"和"lake2"导出所有值 |