Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

nixpy style values and printing #313

Merged
merged 24 commits into from
Nov 23, 2018
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c31148e
[Section] Add nix '__repr__' style
mpsonntag Nov 6, 2018
d4c5d90
[Section] Add property count to __repr__
mpsonntag Nov 6, 2018
a22bea0
[Property] Add nix '__repr__' style
mpsonntag Nov 6, 2018
31ce79a
[Property] Change attribute from _value to _values
mpsonntag Nov 20, 2018
eb48876
[Property] Add 'values' accessor methods
mpsonntag Nov 20, 2018
13d1f64
[Property] Add 'value' deprecation warnings
mpsonntag Nov 20, 2018
73e230e
[Property] Use 'values' instead of 'value'
mpsonntag Nov 20, 2018
35bc91c
[tools/dumper] Use 'values' instead of 'value'
mpsonntag Nov 20, 2018
73edc26
[validation] Use prop 'values' instead of 'value'
mpsonntag Nov 20, 2018
3986581
[tools/dictparser] Prop 'values' replaces 'value'
mpsonntag Nov 20, 2018
8fb4422
[base] Use prop 'values' instead of 'value'
mpsonntag Nov 20, 2018
ac7e0f7
[Property] Provide 'values' and 'value' on init
mpsonntag Nov 21, 2018
b0a0b25
[format] Add Property values to value mapping
mpsonntag Nov 21, 2018
7a3a5b0
[tools/xmlreader] Proper 'values' handling on load
mpsonntag Nov 21, 2018
8156605
[tools/dictparser] Proper 'values' handling on save
mpsonntag Nov 21, 2018
2d1a796
[test] Adapt tests to new Property.values
mpsonntag Nov 21, 2018
bcf5357
[Property] Add pprint method
mpsonntag Nov 22, 2018
3b8d475
[Section] Add pprint method
mpsonntag Nov 22, 2018
66784ae
[doc/tutorial] Add Property.values updates
mpsonntag Nov 22, 2018
62ca6d8
[CHANGELOG] Add latest changes
mpsonntag Nov 22, 2018
25391bb
[Section] Switch '/' to '|' in '__repr__' style
mpsonntag Nov 23, 2018
db866f1
[Property] Move '__repr__' to magic method block
mpsonntag Nov 23, 2018
f6422bd
[Document] Change '__repr__' to new style
mpsonntag Nov 23, 2018
3c0208c
[doc/tutorial] Add new '__repr__' style changes
mpsonntag Nov 23, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,26 @@ until the next release.

# Latest changes in master

...

# Version 1.4.2

## Print methods

`pprint` methods have been added to both `Section` and `Property`
to print whole Section trees with their child sections and properties.
The `__repr__` style of `Section` and `Property` has been changed to
be more similar to the [nixpy](https://github.com/G-Node/nixpy) `__repr__` style.
Printing a `Section` now also features the immediate `Property` child count
in addition to the immediate `Section` child count. See #309.

## Deprecation of 'Property.value' in favor of 'Property.values'

To make working with odML more similar to working with the
metadata part of [nixpy](https://github.com/G-Node/nixpy), the `Property.value`
attribute has been marked deprecated and the `Property.values`
attribute has been added. See #308.

## Uncertainty changes

Uncertainty is now limited to float only. See #294.
Expand Down
129 changes: 63 additions & 66 deletions doc/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ The Document
If you loaded the example odML file, let's have a first look at the Document::

>>> print odmlEX
<Doc 42 by Douglas Adams (2 sections)>
<Doc 42 by D. N. Adams (2 sections)>

As you can see, the printout gives you a short summary of the Document of the
loaded example odML file.
Expand Down Expand Up @@ -293,7 +293,7 @@ Let's check out all attributes with the following commands::
>>> print(odmlEX.parent)
None
>>> print(odmlEX.repository)
http://portal.g-node.org/odml/terminologies/v1.0/terminologies.xml
http://portal.g-node.org/odml/terminologies/v1.1/terminologies.xml
>>> print(odmlEX.version)
42

Expand All @@ -307,7 +307,7 @@ Sections were attached to the Document of our example odML file using the
following command::

>>> print(odmlEX.sections)
[<Section TheCrew[crew] (4)>, <Section TheStarship[starship] (1)>]
[Section[4/2] {name = TheCrew, type = crew, id = ...}, Section[1/7] {name = TheStarship, type = starship, id = ...}]

As expected from the Document printout our example contains two Sections. The
printout and attributes of a Section are explained in the next chapter.
Expand All @@ -324,31 +324,32 @@ look at the first Section in the sections list attached to the Document in our
example odML file::

>>> print(odmlEX.sections['TheCrew'])
<Section TheCrew[crew] (4)>
Section[4/2] {name = TheCrew, type = crew, id = ...}
>>> print(odmlEX.sections[0])
<Section TheCrew[crew] (4)>
Section[4/2] {name = TheCrew, type = crew, id = ...}
>>> print(odmlEX['TheCrew'])
<Section TheCrew[crew] (4)>
Section[4/2] {name = TheCrew, type = crew, id = ...}
>>> print(odmlEX[0])
<Section TheCrew[crew] (4)>
Section[4/2] {name = TheCrew, type = crew, id = ...}

In the following we will call Sections explicitly by their name using the
short cut notation.

The printout of a Section is similar to the Document printout and gives you
already the following information:

- ``<...>`` indicates that you are looking at an object
- ``Section`` tells you that you are looking at an odML Section
- ``TheCrew`` is the name of this Section
- ``[...]`` highlights the type of the Section (here ``crew``)
- ``(4)`` states that this Section has four Sections directly attached to it
- ``[4/2]`` states that this Section has four Sections and two Properties directly attached to it
- ``{...}`` provides ``name``, ``type`` and ``id`` of the Section
- ``name`` is the name of this Section, 'TheCrew' in the example case
- ``type`` provides the type of the Section, 'crew' in the example case
- ``id`` provides the uuid of the Section, the actual value has been omitted in the example to improve readability.


Note that the Section printout tells you nothing about the number of attached
Properties or again about the depth of a possible sub-Section tree below the
directly attached ones. It also only list the type of the Section as one of the
Section attributes. In total, a Section can be defined by the following 5
attributes:
Note that the Section printout tells you nothing about the depth of a possible
sub-Section tree below the directly attached ones. It also only list the type
of the Section as one of the Section attributes. In total, a Section can be
defined by the following 5 attributes:

name
- Returns the name of this Section. Should indicate what kind of
Expand Down Expand Up @@ -413,27 +414,27 @@ To see which Sections are directly attached to the Section 'TheCrew' again use
the following command::

>>> print(odmlEX['TheCrew'].sections)
[<Section Arthur Philip Dent[crew/person] (0)>,
<Section Zaphod Beeblebrox[crew/person] (0)>,
<Section Tricia Marie McMillan[crew/person] (0)>,
<Section Ford Prefect[crew/person] (0)>]
[Section[0/5] {name = Arthur Philip Dent, type = crew/person, id = ...},
Section[0/5] {name = Zaphod Beeblebrox, type = crew/person, id = ...},
Section[0/5] {name = Tricia Marie McMillan, type = crew/person, id = ...},
Section[0/5] {name = Ford Prefect, type = crew/person, id = ...}]

Or, for accessing these sub-Sections::

>>> print(odmlEX['TheCrew'].sections['Ford Prefect'])
<Section Ford Prefect[crew/person] (0)>
Section[0/5] {name = Ford Prefect, type = crew/person, id = ...}
>>> print(odmlEX['TheCrew'].sections[3])
<Section Ford Prefect[crew/person] (0)>
Section[0/5] {name = Ford Prefect, type = crew/person, id = ...}
>>> print(odmlEX['TheCrew']['Ford Prefect'])
<Section Ford Prefect[crew/person] (0)>
Section[0/5] {name = Ford Prefect, type = crew/person, id = ...}
>>> print(odmlEX['TheCrew'][3])
<Section Ford Prefect[crew/person] (0)>
Section[0/5] {name = Ford Prefect, type = crew/person, id = ...}

As you learned, besides sub-Sections, a Section can also have Properties
attached. Let's see which Properties are attached to the Section 'TheCrew'::

>>> print(odmlEX['TheCrew'].properties)
[<Property NameCrewMembers>, <Property NoCrewMembers>]
[Property: {name = NameCrewMembers}, Property: {name = NoCrewMembers}]

The printout and attributes of a Property are explained in the next chapter.

Expand All @@ -445,17 +446,17 @@ Properties need to be called explicitly via the properties function of a
Section. You can then either call a Property by name or by index::

>>> print(odmlEX['TheCrew'].properties['NoCrewMembers'])
<Property NoCrewMembers>
Property: {name = NoCrewMembers}
>>> print(odmlEX['TheCrew'].properties[1])
<Property NoCrewMembers>
Property: {name = NoCrewMembers}

In the following we will only call Properties explicitly by their name.

The Property printout is reduced and only gives you information about the
following:

- ``<...>`` indicates that you are looking at an object
- ``Property`` tells you that you are looking at an odML Property
- ``{...}`` provides the ``name`` of the Property
- ``NoCrewMembers`` is the name of this Property

Note that the Property printout tells you nothing about the number of Values,
Expand All @@ -478,7 +479,7 @@ document
parent
- Returns the parent Section to which this Property was attached to.

value
values
- Returns the metadata of this Property. Can be either a single metadata or
multiple, but homogeneous metadata (all with same dtype and unit). For
this reason, the output is always provided as a list.
Expand Down Expand Up @@ -518,7 +519,7 @@ Let's check which attributes were defined for the Property 'NoCrewMembers'::
Number of crew members
>>> print(odmlEX['TheCrew'].properties['NoCrewMembers'].document)
<Doc 42 by D. N. Adams (2 sections)>
>>> print(odmlEX['TheCrew'].properties['NoCrewMembers'].value)
>>> print(odmlEX['TheCrew'].properties['NoCrewMembers'].values)
[4]
>>> print(odmlEX['TheCrew'].properties['NoCrewMembers'].dtype)
int
Expand All @@ -533,22 +534,22 @@ Let's check which attributes were defined for the Property 'NoCrewMembers'::
>>> print(odmlEX['TheCrew'].properties['NoCrewMembers'].dependency_value)
None

As mentioned the value attribute of a Property can only contain multiple
As mentioned the values attribute of a Property can only contain multiple
metadata when they have the same ``dtype`` and ``unit``, as it is the case for
the Property 'NameCrewMembers'::

>>> print(odmlEX['TheCrew'].properties['NameCrewMembers'].value)
[u'Arthur Philip Dent',
u'Zaphod Beeblebrox',
u'Tricia Marie McMillan',
u'Ford Prefect']
>>> print(odmlEX['TheCrew'].properties['NameCrewMembers'].values)
['Arthur Philip Dent',
'Zaphod Beeblebrox',
'Tricia Marie McMillan',
'Ford Prefect']
>>> print(odmlEX['TheCrew'].properties['NameCrewMembers'].dtype)
person
>>> print(odmlEX['TheCrew'].properties['NameCrewMembers'].unit)
None

NOTE: 'property.value' will always return a copy! Any direct changes to the
returned list will have no affect on the actual property value. If you want to
NOTE: 'property.values' will always return a copy! Any direct changes to the
returned list will have no affect on the actual property values. If you want to
make changes to a property value, either use the 'append', 'extend' and 'remove'
methods or assign a new value list to the property.

Expand Down Expand Up @@ -664,7 +665,7 @@ updated::
>>> print(MYodML)
<Doc 42 by Douglas Adams (1 sections)>
>>> print(MYodML.sections)
[<Section TheCrew[crew] (0)>]
[Section[0/0] {name = TheCrew, type = crew, id = ...}]

>>> print(sec1.document)
<Doc 42 by D. N. Adams (1 sections)>
Expand All @@ -680,12 +681,12 @@ Let's try this with the next Section we create::
parent=sec1)

>>> print(sec2)
<Section Arthur Philip Dent[crew/person] (0)>
Section[0/0] {name = Arthur Philip Dent, type = crew/person, id = ...}

>>> print(sec2.document)
<Doc 42 by D. N. Adams (1 sections)>
>>> print(sec2.parent)
<Section TheCrew[crew] (1)>
[Section[1/0] {name = TheCrew, type = crew, id = ...}

Note that all of our created Sections do not contain any Properties yet. Let's
see if we can change this...
Expand All @@ -698,7 +699,7 @@ Let's create our first Property::

>>> prop1 = odml.Property(name="Gender",
definition="Sex of the subject",
value="male")
values="male")

Note that again, only the name attribute is obligatory for creating a Property.
The remaining attributes can be defined later on, or are automatically
Expand Down Expand Up @@ -752,16 +753,16 @@ automatically update its parent attribute::
>>> print(prop1.document)
<Doc 42 by D. N. Adams (1 sections)>
>>> print(prop1.parent)
<Section Arthur Philip Dent[crew/person] (0)>
Section[0/1] {name = Arthur Philip Dent, type = crew/person, id = ...}

Next, let us create a Property with multiple metadata entries::

>>> prop2 = odml.Property(name="NameCrewMembers",
definition="List of crew members names",
value=["Arthur Philip Dent",
"Zaphod Beeblebrox",
"Tricia Marie McMillan",
"Ford Prefect"],
values=["Arthur Philip Dent",
"Zaphod Beeblebrox",
"Tricia Marie McMillan",
"Ford Prefect"],
dtype=odml.DType.person)

As you learned before, in such a case, the metadata entries must be
Expand All @@ -776,12 +777,12 @@ previously created Section 'TheCrew'::
Note that it is also possible to add a metadata entry later on::

>>> prop2.append("Blind Passenger")
>>> print(MYodML['TheCrew'].properties['NameCrewMembers'].value)
[u'Arthur Philip Dent',
u'Zaphod Beeblebrox',
u'Tricia Marie McMillan',
u'Ford Prefect',
u'Blind Passenger']
>>> print(MYodML['TheCrew'].properties['NameCrewMembers'].values)
['Arthur Philip Dent',
'Zaphod Beeblebrox',
'Tricia Marie McMillan',
'Ford Prefect',
'Blind Passenger']


The tuple datatype you might have noticed in the dtype table above has to be
Expand All @@ -794,17 +795,17 @@ by brackets and separated by a semicolon.

>>> pixel_prop = odml.Property(name="pixel map")
>>> pixel_prop.dtype = "2-tuple"
>>> pixel_prop.value = ["(1; 2)", "(3; 4)"]
>>> pixel_prop.values = ["(1; 2)", "(3; 4)"]

>>> voxel_prop = odml.Property(name="voxel map")
>>> voxel_prop.dtype = "3-tuple"
>>> voxel_prop.value = "(1; 2; 3)"
>>> voxel_prop.values = "(1; 2; 3)"

Please note, that inconsistent tuple values will raise an error:

>>> tprop = odml.Property(name="tuple fail")
>>> tprop.dtype = "3-tuple"
>>> tprop.value = ["(1; 2)"]
>>> tprop.values = ["(1; 2)"]


Printing XML-representation of an odML file:
Expand Down Expand Up @@ -883,13 +884,13 @@ After creating a Property with metadata the data type can be changed and the
format of the corresponding entry will converted to the new data type, if the
new format is valid for the given metadata::

>>> test_dtype_conv = odml.Property('p', value=1.0)
>>> print(test_dtype_conv.value)
>>> test_dtype_conv = odml.Property('p', values=1.0)
>>> print(test_dtype_conv.values)
[1.0]
>>> print(test_dtype_conv.dtype)
float
>>> test_dtype_conv.dtype = odml.DType.int
>>> print(test_dtype_conv.value)
>>> print(test_dtype_conv.values)
[1]
>>> print(test_dtype_conv.dtype)
int
Expand All @@ -899,22 +900,18 @@ If the conversion is invalid a ValueError is raised.
Also note, that during such a process metadata loss may occur if a float is
converted to an integer and then back to a float::

>>> test_dtype_conv = odml.Property('p', value=42.42)
>>> print(test_dtype_conv.value)
>>> test_dtype_conv = odml.Property('p', values=42.42)
>>> print(test_dtype_conv.values)
[42.42]
>>> test_dtype_conv.dtype = odml.DType.int
>>> test_dtype_conv.dtype = odml.DType.float
>>> print(test_dtype_conv.value)
>>> print(test_dtype_conv.values)
[42.0]


Advanced knowledge on Properties
--------------------------------

Dependencies & dependency values
********************************
(coming soon)

Advanced knowledge on Sections
------------------------------

Expand Down
4 changes: 2 additions & 2 deletions odml/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,8 @@ def itervalues(self, max_depth=None, filter_func=lambda x: True):
:type filter_func: function
"""
for prop in [p for p in self.iterproperties(max_depth=max_depth)]:
if filter_func(prop.value):
yield prop.value
if filter_func(prop.values):
yield prop.values

def contains(self, obj):
"""
Expand Down
3 changes: 2 additions & 1 deletion odml/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ class Property(Format):
_map = {
'dependencyvalue': 'dependency_value',
'type': 'dtype',
'id': 'oid'
'id': 'oid',
'value': 'values'
}
_rdf_map = {
'id': _ns.hasId,
Expand Down
Loading