This page explains ways that pages can have more control over the display and conversion of units, in particular for properties of datatype Quantity. This feature makes annotation more flexible: everybody can view and enter data in his or her preferred unit without restricting mutual understanding. For example, some people might prefer a distance given in "miles" over one given in "km". In other cases, it might not be suitable to display a distance in "km" if "microns" are more appropriate.
Datatypes and properties with unit conversions
SMW has built-in support for some types that can handle units (e.g. Temperature). Types that support units can accept, convert, and display values in several different units. You can see this in the factbox of articles like "Berlin", where the area is given in multiple units.
In order to support such features, SMW needs to know how to convert values from one unit into another. This is rather easy in many cases, but can also involve more complex computation in other situations. We distinguish two cases:
- Conversion between the desired units is proportional, i.e. you just have to multiply one value with a fixed conversion factor to get the value in another unit. For example, this is the case for converting between kilometres and miles.
- Conversion between units is not proportional and more complex computations are needed. For example, this occurs for temperatures, since you need to add and multiply in order to get from °C to °F.
For all unit conversions of the first kind, the datatype Quantity can be used to define units and conversion factors for properties in the wiki. For the second situation, we discuss some possibilities below.
Converting between proportional units
SMW provides the datatype Quantity for declaring properties whose values consist of a number together with a unit of measurement. A "unit" can be any text label that does not start with a number, such as "miles", "km²", or "m/s". To make a unit (or an alternative writing of a unit) available, it must first be declared on the page of the property as explained below. Only declared units can be used, all others will be rejected as input errors. Therefore a property of type Quantity is of little use until at least one unit has been declared. The advantage of this strict system is that SMW can compare property values among each other, even if different units have been used to write them. Every input value clearly specifies a "quantity" (like an amount of time or a distance) that is understood even if written in a variety of ways. The property value is really such a quantity (and this is what is stored), not the particular text that has been used to write it on some wiki page (this text or its original unit is not stored). We already have seen a similar behavior for other datatypes, for example SMW does not store whether a number was written as "2" or "2.0" but always treat it as the same number.
To use the unit conversion in SMW, you first need to create a suitable property. As usual, you may first want to use the wiki search and Special:Properties to check if there already is a property that serves your purpose. If not, create a new article in the property namespace. For example, suppose that we want to introduce a Property:Power to measure the physical quantity of power. In the new article, you should first write some sentences on the purpose and use of this new property. In our case this would say that we mean the physical quantity that is usually measured in Watt. This also helps others to find and reuse your type when searching for keywords. To specify the datatype, you can add the annotation
somewhere on the page (ideally in a sentence). To declare the supported units, you use a special property corresponds to. For example, to specify the main unit of the new datatype for power, we add
[[Corresponds to::1 W]]
The value "1 W" states two things: (1) the type understands the unit "W" and (2) the unit "W" is its main unit (that is what the "1" is for). The main unit is the default choice for displaying values of this datatype, and it is assumed whenever the user enters a plain number without giving any unit. It is easy to specify further units, e.g.
[[Corresponds to::0.001 kW]] [[Corresponds to::0.0013410220 hp]].
This says that the type also understands the units "kW" and "hp". Now reading the annotations makes more sense: 1 W corresponds to 0.001 kW which in turn corresponds to 0.0013410220 hp. In this way, you can support arbitrary units, so long as their relationship to the main unit can be described in this easy manner.
In many cases, there are multiple ways of referring to one unit. For instance we would like to allow users to write "W" as well as "Watt" and maybe even "Watts". A short way of doing this is to separate additional units with "," instead of making multiple "corresponds to" statements with the same factor. For example we would write:
[[Corresponds to::1 W, Watt, Watts]] [[Corresponds to::0.0013410220 hp,bhp,horsepower]]
In this case, the main unit is the very first unit in the "corresponds to" statement for 1, in our example "W". The property will understand all the units defined in "corresponds to" statements, and will show conversions between them (without duplicates, i.e. SMW does not display "W" and "Watt").
Internally, the values will all be converted to the main unit, and the RDF export will only show the value in this unit. Inputs that do not include a unit at all are always understood as values in the main unit. From this viewpoint, unit conversion is simply a kind of pre-processing (of user inputs) and post-processing (for display) that makes it easier for users to deal with units. The display of units within the wiki is highly customizable and need not involve the main unit, see below.
Hint: If many properties use the same unit declarations (e.g. "Property:Width" and "Property:Height") then it is a good idea to put the unit declarations into a template that can be included on all property pages. In this way it can be ensured that properties that measure the same quantity do always support the same units.
Note: Units must always be written after the number in a property value. Prefix units like in "$100" are not supported.
Unit conversions that are not proportional
With the datatype Quantity you can only specify a proportional conversion factor, a multiplier. So you cannot have different bases for different units, logarithmic scale conversions, etc. For example, you cannot define a custom conversion for properties that should convert temperatures from degrees Celsius to Fahrenheit (a conversion that involves not only multiplication but also addition). However, in the case of temperature, SMW already supplies a built-in datatype Temperature that handles this conversion, but this might not be true in other cases.
SMW does not allow specifying customized non-proportional units in the wiki. One workaround for this is to use datatype Number and to omit the unit in the annotation and only write it in the wiki text. This removes the convenient pre- and post-processing features of unit support but offers the same power in terms of most other features (queries, export, etc.). One could also use a template with parser functions to implement certain unit conversions, but this usually leads to complicated wiki text and less efficient processing.
A better solution if a new unit is really needed is to write a small PHP script that implements the required conversion. It is not difficult to extend SMW in this fashion, and one could simply copy and adjust the code for Type:Temperature (which is only a little longer than 100 lines, including comments). Upon implementing such a custom type, existing properties of Type:Number can be changed to the new type without any negative effects on existing articles. When confronted with unsupported units, custom types will still behave like simple number datatypes.
Customizing the display of units
A single property can support a broad range of units. For example, a single length property can easily support both light years and nanometers. Even if only some of these units are needed in a particular property, it still might be useful to declare all relevant units in a template as described above. However, if someone uses a property "Elevation" to specify the height of a mountain, then it would hardly be useful to display this value in light years or nanometers.
SMW therefore allows you to specify which units a property should display from all the units that it supports. If no preferences on display are given, a property will display all of its units, with the main unit (the one with conversion factor 1) first.
To specify custom display units, add the special property display units to the property's page, mentioning each unit you want displayed separated by commas. For example, the article Property:Height could contain the statements:
This results in the factbox displaying only those three units for values of the property Height, even though it might support a dozen of other units. Similarly, the tooltip for each such value will show those conversions. This customization works for all properties that use types with unit support.
If you change the first display unit, consider displaying the main unit to users as one of the other display units, since SMW still converts values to the main unit when storing them.
The use of spaces within unit labels has been addressed in #1718.
Custom units in earlier versions of SMW
Up to Semantic MediaWiki 1.5.6, datatypes had their own wiki pages and custom units were declared on a datatype page, not on the property page. Additionally it was possible to define custom datatypes. The datatype Quantity did not exist and the both the datatype Number and all custom unit conversion types would accept unknown units as inputs. This has been changed to the current system for simplifying the whole process (one namespace less, less pages, less special cases). To re-use unit declarations on many property pages like in the old system, unit declarations can simply be put into templates that are included on many property pages.
See Help:Custom units 1.5 for a documentation of the old system.
Custom units en 1.6.0