示例#1
0
class IAggregateDescription(Interface):
    """
    Mixin of fields related to aggregating multiple data points into
    a single descriptive aggretate point.  All fields optional, and
    only considered relevant to aggregation of data from multiple
    sources or samples.

    'distribution' attribute would have values that look like:
    [{ "value": 75.0, "sample_size": 8 }, { "value": 80, "sample_size": 10}]

    This data is sufficient to compute:

        - The sum of sample sizes.
        - The weighted mean.
        - The original numerator values as value/100.0 * sample_size
          - Presuming the value looks like a percentage.
        - The arithmetic mean.
        - Distribution plot.
        - Median, quartile boundary, and therefore box plot.
    """

    distribution = schema.List(
        title=_(u'Distribution data'),
        description=_(u'List of dict containing value, sample size for each '
                      u'sample in aggregation.'),
        required=False,
        value_type=schema.Dict(key_type=schema.BytesLine(),
                               value_type=schema.Object(
                                   schema=Interface,
                                   description=u'Value, may be int or float')))
示例#2
0
class INamedDataSequence(form.Schema, IDataSeries, ISeriesDisplay):
    """Named category seqeuence with embedded data stored as content"""

    form.fieldset(
        'display',
        label=u"Display settings",
        fields=[
            'color',
            'show_trend',
            'trend_width',
            'trend_color',
            'display_precision',
            'point_labels',
        ],
    )

    input = schema.Text(
        title=_(u'Data input'),
        description=_(u'Comma-separated records, one per line '
                      u'(name, numeric value, [note], [URL]). '
                      u'Note and URL are optional.'),
        default=u'',
        required=False,
    )

    # data field to store CSV source:
    form.omitted('data')
    data = schema.List(
        title=_(u'Data'),
        description=_(u'Data points for series: name, value; values are '
                      u'either whole/integer or decimal numbers.'),
        value_type=schema.Object(schema=INamedDataPoint, ),
        readonly=True,
    )
示例#3
0
class ITimeSeriesCollection(IDataCollection):
    """
    Time series interface for configured range of time for all data
    series contained.  Adds date range configuration to collection.
    """

    start = schema.Date(
        title=_(u'Start date'),
        required=False,
        )

    end = schema.Date(
        title=_(u'End date'),
        required=False,
        )

    frequency = schema.Choice(
        title=u'Chart frequency',
        vocabulary=FREQ_VOCAB,
        default='monthly',
        )

    @invariant
    def validate_start_end(obj):
        if not (obj.start is None or obj.end is None) and obj.start > obj.end:
            raise Invalid(_(u"Start date cannot be after end date."))
示例#4
0
class ISeriesQuickStyles(form.Schema):
    """Interface for quick line styles (commonly used) for style book"""

    form.widget(color=NativeColorFieldWidget)
    color = schema.TextLine(
        title=_(u'Series color'),
        description=_(u'If omitted, color will be selected from defaults.'),
        required=False,
        default=u'Auto',
    )

    marker_style = schema.Choice(
        title=_(u'Marker style'),
        description=_(u'Shape/type of the point-value marker.'),
        vocabulary=SimpleVocabulary([
            SimpleTerm(value=u'diamond', title=u'Diamond'),
            SimpleTerm(value=u'circle', title=u'Circle'),
            SimpleTerm(value=u'square', title=u'Square'),
            SimpleTerm(value=u'x', title=u'X'),
            SimpleTerm(value=u'plus', title=u'Plus sign'),
            SimpleTerm(value=u'dash', title=u'Dash'),
            SimpleTerm(value=u'triangle-up', title=u'Triangle (upward)'),
            SimpleTerm(value=u'triangle-down', title=u'Triangle (downward)'),
        ]),
        default=u'square',
    )
示例#5
0
class INamedBase(Interface):
    """Mix-in schema for name field"""

    name = schema.TextLine(
        title=_(u'Name'),
        description=_(u'Series-unique name or category for data point.'),
        required=True,
        )

    def identity():
        """return self.name"""
示例#6
0
class IMeasureSeriesProvider(form.Schema, IDataSeries, ILineDisplay):

    form.widget(measure=ContentTreeFieldWidget)
    measure = schema.Choice(
        title=u'Bound measure',
        description=u'Measure definition that defines a function to apply '
                    u'to a dataset of forms to obtain a computed value for '
                    u'each as a data-point.',
        source=UUIDSourceBinder(
            portal_type=MEASURE_DEFINITION_TYPE,
            ),
        )

    dataset = schema.Choice(
        title=u'Data set (collection)',
        description=u'Select a dataset that enumerates which forms are '
                    u'considered part of the data set to query for data. '
                    u'You must select a dataset within the same measure '
                    u'group in which the bound measure definition is '
                    u'contained.',
        source=MeasureGroupParentBinder(
            portal_type='uu.formlibrary.setspecifier',
            ),
        required=False,
        )

    summarization_strategy = schema.Choice(
        title=u'Summarization strategy',
        description=u'How should data be summarized into a single value '
                    u'when multiple competing values for date or name '
                    u'are found in the data stream provided by the measure '
                    u'and data set?  For example you may average or sum '
                    u'the multiple values, take the first or last, '
                    u'or you may choose to treat such competing values as '
                    u'a conflict, and omit any value on duplication.',
        vocabulary=VOCAB_SUMMARIZATION,
        default='AVG',
        )

    form.omitted('data')
    data = schema.List(
        title=_(u'Data'),
        description=_(u'Data points computed from bound dataset, measure '
                      u'selected.  Should return an empty list if any '
                      u'bindings are missing. '
                      u'Whether the data point key/identity type is a date '
                      u'or a name will depend on the type of chart '
                      u'containing this data provider.'),
        value_type=schema.Object(
            schema=IDataPoint,
            ),
        readonly=True,
        )
示例#7
0
class IChartStyleBook(IChartDisplay):
    """
    Style book for charts, can contain (as folder) ILineStyle items,
    in an ordered manner.
    """

    goal = schema.Float(
        title=_(u'Goal'),
        description=_(u'Common goal value as decimal number.  If each '
                      u'series has different respective goals, edit '
                      u'those goals on each series.'),
        required=False,
        )

    # hide fields that are per-chart-specific
    form.omitted('x_label')
    form.omitted('y_label')
示例#8
0
class IDataPoint(IAggregateDescription):
    """Data point contains single value and optional note and URI"""

    value = schema.Float(
        title=_(u'Number value'),
        description=_(u'Decimal number value.'),
        default=0.0,
    )

    note = schema.Text(
        title=_(u'Note'),
        description=_(u'Note annotating the data value for this point.'),
        required=False,
    )

    uri = schema.BytesLine(
        title=_(u'URI'),
        description=_(u'URI/URL or identifier to source of data'),
        required=False,
    )

    sample_size = schema.Int(
        title=_(u'Sample size (N)'),
        description=u'Sample size, may be computed denominator of a '
        u'population or subpopulation sampled.',
        required=False,
    )

    def identity():
        """
示例#9
0
class IDateBase(Interface):
    """Mix-in schema with date field"""

    date = schema.Date(
        title=_(u'Date'),
        required=True,
        )

    def identity():
        """return self.date"""
示例#10
0
class ISeriesDisplay(form.Schema):
    """
    Common display settings for visualizing a series as either a bar
    or line chart.
    """

    form.widget(color=ColorpickerFieldWidget)
    color = schema.TextLine(
        title=_(u'Series color'),
        description=_(u'If omitted, color will be selected from defaults.'),
        required=False,
        default=u'Auto',
        )

    show_trend = schema.Bool(
        title=_(u'Show trend-line?'),
        description=_(u'Display a linear trend line?  If enabled, uses '
                      u'configuration options specified.'),
        default=False,
        )

    trend_width = schema.Int(
        title=_(u'Trend-line width'),
        description=_(u'Line width of trend-line in pixel units.'),
        default=2,
        )

    form.widget(trend_color=ColorpickerFieldWidget)
    trend_color = schema.TextLine(
        title=_(u'Trend-line color'),
        description=_(u'If omitted, color will be selected from defaults.'),
        required=False,
        default=u'Auto',
        )

    display_precision = schema.Int(
        title=u'Digits after decimal point (display precision)?',
        description=u'When displaying a decimal value, how many places '
                    u'beyond the decimal point should be displayed in '
                    u'output?  Default: two digits after the decimal point.',
        default=1,
        )

    point_labels = schema.Choice(
        title=u'Show point labels?',
        description=u'Show labels above data-point markers for this series?',
        default='defer',
        vocabulary=SimpleVocabulary([
                SimpleTerm('defer', title=u'Defer to chart default'),
                SimpleTerm('show', title=u'Show labels'),
                SimpleTerm('omit', title=u'Omit labels'),
            ])
        )
示例#11
0
class INamedSeriesChart(IBaseChart, IDataCollection, IChartDisplay):
    """
    Named/categorical chart: usually a bar chart with x-axis containing
    categorical enumerated names/labels, and Y-axis representing values
    for that label.
    """

    chart_type = schema.Choice(
        title=_(u'Chart type'),
        description=_(u'Type of chart to display.'),
        vocabulary=SimpleVocabulary([
            SimpleTerm(value=u'bar', title=u'Bar chart'),
            SimpleTerm(value=u'stacked', title=u'Stacked bar chart'),
            ]),
        default=u'bar',
        )

    def series():
        """
示例#12
0
class ITimeDataSequence(form.Schema, IDataSeries, ILineDisplay):
    """Content item interface for a data series stored as content"""

    input = schema.Text(
        title=_(u'Data input'),
        description=_(u'Comma-separated records, one per line '
                      u'(date, numeric value, [note], [URL]). '
                      u'Note and URL are optional. Date '
                      u'should be in MM/DD/YYYY format.'),
        default=u'',
        required=False,
        )

    label_default = schema.Choice(
        title=_(u'Label default'),
        description=_(u'Default format for X-Axis labels.'),
        default='locale',
        vocabulary=DATE_AXIS_LABEL_CHOICES,
        )

    form.omitted('data')
    data = schema.List(
        title=_(u'Data'),
        description=_(u'Data points for time series: date, value; values are '
                      u'either whole/integer or decimal numbers.'),
        value_type=schema.Object(
            schema=ITimeSeriesDataPoint,
            ),
        readonly=True,
        )
示例#13
0
class IDataReport(form.Schema, IOrderedContainer, IAttributeUUID):
    """
    Ordered container/folder of contained charts providing ITimeSeriesChart.
    """

    title = schema.TextLine(
        title=_(u'Title'),
        description=_(u'Report title; may be displayed in output.'),
        required=False,
        )

    description = schema.Text(
        title=_(u'Description'),
        description=_(u'Textual description of the report.'),
        required=False,
        )

    timeseries_default_type = schema.Choice(
        title=u'Default plot type for time-series',
        vocabulary=VOCAB_PLOT_TYPES,
        default=u'line',
        )
示例#14
0
class IDataSeries(form.Schema):
    """Iterable of IDataPoint objects"""

    title = schema.TextLine(
        title=_(u'Title'),
        description=_(u'Name of data series; may be displayed as a label.'),
        required=True,
        )

    def __iter__():
        """
        Return iterable of date, number data point objects providing
        (at least) IDataPoint.
        """

    def __len__():
        """Return number of data points"""

    def display_value(point):
        """Return normalized string display value for point"""

    def excluded():
        """
示例#15
0
class IDataPoint(Interface):
    """Data point contains single value and optional note and URI"""

    value = schema.Float(
        title=_(u'Number value'),
        description=_(u'Decimal number value.'),
        default=0.0,
        )

    note = schema.Text(
        title=_(u'Note'),
        description=_(u'Note annotating the data value for this point.'),
        required=False,
        )

    uri = schema.BytesLine(
        title=_(u'URI'),
        description=_(u'URI/URL or identifier to source of data'),
        required=False,
        )

    def identity():
        """
示例#16
0
class IBaseChart(form.Schema, ILocation, IAttributeUUID, IDataCollection,
                 IChartDisplay):
    """Base chart (content item) interface"""

    form.omitted('__name__')

    form.fieldset('goal',
                  label=u'Goal',
                  fields=[
                      'show_goal',
                      'goal',
                      'goal_color',
                  ])

    form.fieldset('legend',
                  label=u'Axes & Legend',
                  fields=[
                      'legend_placement',
                      'legend_location',
                      'x_label',
                      'y_label',
                      'units',
                  ])

    form.fieldset('display',
                  label=u"Display",
                  fields=[
                      'width',
                      'width_units',
                      'height',
                      'height_units',
                      'chart_styles',
                      'point_labels',
                  ])

    form.fieldset(
        'about',
        label=u"About",
        fields=['info'],
    )

    directives.widget('stylebook',
                      CustomRootRelatedWidget,
                      pattern_options={
                          'selectableTypes': ['uu.chart.stylebook'],
                          'maximumSelectionSize':
                          1,
                          'baseCriteria': [{
                              'i': 'portal_type',
                              'o': 'plone.app.querystring.operation.string.is',
                              'v': 'uu.chart.stylebook',
                          }]
                      })
    stylebook = schema.BytesLine(
        title=u'Bound theme',
        description=u'If a theme is bound, any updates to that theme '
        u'will OVER-WRITE display configuration saved '
        u'on this chart.',
        required=False,
        constraint=is_content_uuid)

    info = RichText(
        title=_(u'Informative notes'),
        description=_(u'This allows any rich text and may contain free-form '
                      u'notes about this chart; displayed in report output.'),
        required=False,
    )
示例#17
0
 def validate_start_end(obj):
     if not (obj.start is None or obj.end is None) and obj.start > obj.end:
         raise Invalid(_(u"Start date cannot be after end date."))
示例#18
0
class IBaseChart(
        form.Schema,
        ILocation,
        IAttributeUUID,
        IDataCollection,
        IChartDisplay):
    """Base chart (content item) interface"""

    form.omitted('__name__')

    form.fieldset(
        'goal',
        label=u'Goal',
        fields=[
            'show_goal',
            'goal',
            'goal_color',
            ]
        )

    form.fieldset(
        'legend',
        label=u'Axes & Legend',
        fields=[
            'legend_placement',
            'legend_location',
            'x_label',
            'y_label',
            'units',
            ]
        )

    form.fieldset(
        'display',
        label=u"Display",
        fields=[
            'width',
            'width_units',
            'height',
            'height_units',
            'chart_styles',
            'point_labels',
            ]
        )

    form.fieldset(
        'about',
        label=u"About",
        fields=['info'],
        )

    form.widget(stylebook=ContentTreeFieldWidget)
    stylebook = schema.Choice(
        title=u'Bound stylebook',
        description=u'If a stylebook is bound, any updates to that style '
                    u'book will OVER-WRITE display configuration saved '
                    u'on this chart.',
        source=UUIDSourceBinder(
            portal_type=STYLEBOOK_TYPE,
            ),
        required=False,
        )

    info = RichText(
        title=_(u'Informative notes'),
        description=_(u'This allows any rich text and may contain free-form '
                      u'notes about this chart; displayed in report output.'),
        required=False,
        )
示例#19
0
class ILineDisplayCore(form.Schema, ISeriesDisplay):
    """
    Mixin interface for display-line configuration metadata for series line.
    """

    line_width = schema.Int(
        title=_(u'Line width'),
        description=_(u'Width/thickness of line in pixel units.'),
        default=2,
        )

    marker_style = schema.Choice(
        title=_(u'Marker style'),
        description=_(u'Shape/type of the point-value marker.'),
        vocabulary=SimpleVocabulary([
            SimpleTerm(value=u'diamond', title=u'Diamond'),
            SimpleTerm(value=u'circle', title=u'Circle'),
            SimpleTerm(value=u'square', title=u'Square'),
            SimpleTerm(value=u'x', title=u'X'),
            SimpleTerm(value=u'plus', title=u'Plus sign'),
            SimpleTerm(value=u'dash', title=u'Dash'),
            SimpleTerm(value=u'filledDiamond', title=u'Filled diamond'),
            SimpleTerm(value=u'filledCircle', title=u'Filled circle'),
            SimpleTerm(value=u'filledSquare', title=u'Filled square'),
            ]),
        default=u'square',
        )

    marker_size = schema.Float(
        title=_(u'Marker size'),
        description=_(u'Size of the marker (diameter or circle, length of '
                      u'edge of square, etc) in decimal pixels.'),
        required=False,
        default=9.0,
        )

    marker_width = schema.Int(
        title=_(u'Marker line width'),
        description=_(u'Line width of marker in pixel units for '
                      u'non-filled markers.'),
        required=False,
        default=2,
        )

    form.widget(marker_color=ColorpickerFieldWidget)
    marker_color = schema.TextLine(
        title=_(u'Marker color'),
        description=_(u'If omitted, color will be selected from defaults.'),
        required=False,
        default=u'Auto',
        )

    break_lines = schema.Bool(
        title=u'Break lines?',
        description=u'When a value is missing for name or date on the '
                    u'X axis, should the line be broken/discontinuous '
                    u'such that no line runs through the empty/null '
                    u'value?  This defaults to True, which means that '
                    u'no line will run from adjacent values through the '
                    u'missing value.',
        default=True,
        )
示例#20
0
class IChartDisplay(form.Schema):
    """
    Display configuration for chart settings (as a whole).
    """

    width = schema.Int(
        title=_(u'Width'),
        description=_(u'Display width of chart, including Y-axis labels, '
                      u'grid, and legend (if applicable) in units '
                      u'configured.'),
        default=100,
        )

    width_units = schema.Choice(
        title=_(u'Units of width'),
        vocabulary=WIDTH_UNITS,
        default='%',
        )

    height = schema.Int(
        title=_(u'Height'),
        description=_(u'Display height of chart in units configured '
                      u'(either as percentage of width, or in pixels).'),
        default=50,
        )

    height_units = schema.Choice(
        title=_(u'Units of height'),
        vocabulary=HEIGHT_UNITS,
        default='2:1',
        )

    show_goal = schema.Bool(
        title=_(u'Show goal-line?'),
        description=_(u'If defined, show (constant horizontal) goal line?'),
        default=False,
        )

    form.widget(goal_color=ColorpickerFieldWidget)
    goal_color = schema.TextLine(
        title=_(u'Goal-line color'),
        description=_(u'If omitted, color will be selected from defaults.'),
        required=False,
        default=u'Auto',
        )

    form.order_after(chart_type='description')
    chart_type = schema.Choice(
        title=_(u'Chart type'),
        description=_(u'Type of chart to display.'),
        vocabulary=VOCAB_PLOT_TYPES,
        default=u'line',
        )

    legend_placement = schema.Choice(
        title=_(u'Legend placement'),
        description=_(
            u'Where to place legend in relationship to the grid.'
            u'Note: the legend is disabled for less than two '
            u'series/line unless the tabular legend is selected.'
            ),
        vocabulary=SimpleVocabulary((
            SimpleTerm(value=None, token=str(None), title=u'Legend disabled'),
            SimpleTerm(value='outside', title=_(u'Outside grid')),
            SimpleTerm(value='inside', title=_(u'Inside grid')),
            SimpleTerm(value='tabular', title=_(
                u'Tabular legend with data, below plot')),
            )),
        required=False,
        default='outside',
        )

    legend_location = schema.Choice(
        title=_(u'Legend location'),
        description=_(u'Select a directional position for legend. '
                      u'This setting is ignored if either the tabular '
                      u'legend placement is selected or if the '
                      u'legend is hidden (for less than two series).'),
        vocabulary=SimpleVocabulary((
            SimpleTerm(value='nw', title=_(u'Top left')),
            SimpleTerm(value='n', title=_(u'Top')),
            SimpleTerm(value='ne', title=_(u'Top right')),
            SimpleTerm(value='e', title=_(u'Right')),
            SimpleTerm(value='se', title=_(u'Bottom right')),
            SimpleTerm(value='s', title=_(u'Bottom')),
            SimpleTerm(value='sw', title=_(u'Bottom left')),
            SimpleTerm(value='w', title=_(u'Left')),
            )),
        required=False,
        default='e',  # right hand side
        )

    x_label = schema.TextLine(
        title=_(u'X axis label'),
        default=u'',
        required=False,
        )

    y_label = schema.TextLine(
        title=_(u'Y axis label'),
        default=u'',
        required=False,
        )

    form.widget(chart_styles=TextAreaFieldWidget)
    chart_styles = schema.Bytes(
        title=_(u'Chart styles'),
        description=_(u'CSS stylesheet rules for chart (optional).'),
        required=False,
        )

    point_labels = schema.Choice(
        title=u'Show point labels?',
        description=u'Show labels above data-point markers?  '
                    u'This may be overridden on individual lines/series.',
        default='show',
        vocabulary=SimpleVocabulary([
                SimpleTerm('show', title=u'Show labels'),
                SimpleTerm('omit', title=u'Omit labels'),
            ])
        )
示例#21
0
 def validate_start_end(obj):
     if not (obj.start is None or obj.end is None) and obj.start > obj.end:
         raise Invalid(_(u"Start date cannot be after end date."))
示例#22
0
class IDataCollection(Interface):
    """
    Collection of one or more (related) data series and associated metadata.
    Usually the logical component of a chart with multiple data series.
    """

    title = schema.TextLine(
        title=_(u'Title'),
        description=_(u'Data collection name or title; may be displayed '
                      u'in legend.'),
        required=False,
        )

    description = schema.Text(
        title=_(u'Description'),
        description=_(u'Textual description of the data collection.'),
        required=False,
        )

    units = schema.TextLine(
        title=_(u'Units'),
        description=_(u'Common set of units of measure for the data '
                      u'series in this collection.  If the units '
                      u'for series are not shared, then define '
                      u'respective units on the series themselves. '
                      u'May be displayed as part of Y-axis label.'),
        required=False,
        )

    goal = schema.Float(
        title=_(u'Goal'),
        description=_(u'Common goal value as decimal number.  If each '
                      u'series has different respective goals, edit '
                      u'those goals on each series.'),
        required=False,
        )

    range_min = schema.Float(
        title=_(u'Range minimum'),
        description=_(u'Minimum anticipated value of any data point '
                      u'(optional).'),
        required=False,
        )

    range_max = schema.Float(
        title=_(u'Range maximum'),
        description=_(u'Maximum anticipated value of any data point '
                      u'(optional).'),
        required=False,
        )

    def series():
        """
        return a iterable of IDataSeries objects.
        """

    def identities():
        """