xyReading, a IIIF extension for XY spectra (version 1)
xyReading tells a client how to read an XY curve (a spectrum) out of a Dataset content resource of a IIIF Presentation 3 document: which columns hold x and y, how their axes are titled, and which correction turns the raw file into the curve.
Where it appears
Only on a content resource of type Dataset, usually an annotation body. Any other resource MUST NOT carry it. A document that uses it lists this context first in its @context and the Presentation 3 context last:
"@context": ["https://manuspectrum.huma-num.fr/iiif/context/xy-reading/1.jsonld", "http://iiif.io/api/presentation/3/context.json"]
A document that also declares IIIF Authorization 2.0 services lists the Authorization 2.0 context between the two:
"@context": ["https://manuspectrum.huma-num.fr/iiif/context/xy-reading/1.jsonld", "http://iiif.io/api/auth/2/context.json", "http://iiif.io/api/presentation/3/context.json"]
The Presentation 2.1 routes carry the same object, with this context before the Presentation 2 context.
Advisory
Clients MAY use xyReading to draw the curve; they SHOULD fall back to their own reading of the file when they do not, and MUST ignore keys they do not know. Every key published is one the ManuSpectrum reader applies.
Keys
type:XYReading- The type of the object. Required.
conformsTo- The documentation of the version of xyReading the object follows (this page).
dialect- CSV dialect of the file (CSV on the Web terms):
delimiter,headerRowCount,encoding. Given for the files ManuSpectrum writes. columns- The columns read, in order:
index(from 0) androle. index- Zero-based index of a column.
role- What a column holds:
x(the x axis),yLeftandyRight(a measurement on the left or right axis),reference(the white reference),dark(the dark current),ignore. x- The x axis:
label(a IIIF language map) andreversed(true when the axis is drawn from right to left; the rows keep the file's order). y- The y axes, in order:
axis(leftorright) andlabel. reversed- Whether the x axis is drawn from right to left.
multiY- How several measurement columns combine:
reference-normalizedivides the measurement by the reference (see corrections). corrections- The corrections applied, in order. Version 1 knows
reference-normalize:expression(y - dark) / (reference - dark),darkDefaultthe dark value without a dark column (0),epsilonthe smallest denominator divided by, andonInvaliddrop-point: a row with a missing value, a non-finite value or a denominator below epsilon is left out of the curve. An empty list says the file already holds the curve. derivedFrom- The raw file the Dataset was derived from (PROV
wasDerivedFrom):id,type,format,labeland, for a raw text file, its ownxyReading(columns and corrections).
The Dataset is never decimated, whatever its size. mirador-xyviewer does not plot a Dataset larger than 5 MB; such a file still plots in the ManuSpectrum Explorer.
Restricted data (IIIF Authorization)
Open data needs no credential. A restricted spectrum, annotation or content state answers 401 with a description that names the IIIF Authorization services; annotation pages and collections are never refused: they list what the reader may see and declare the same services.
- Login: the viewer opens https://manuspectrum.huma-num.fr/iiif/auth/login in a new window (IIIF Auth 1.0
loginprofile, Auth 2.0activeprofile). The reader signs in to ManuSpectrum there; the window then says so and can be closed. - Token: the viewer loads
https://manuspectrum.huma-num.fr/iiif/auth/1/token(Auth 1.0) orhttps://manuspectrum.huma-num.fr/iiif/auth/2/token(Auth 2.0) in a hidden frame with itsmessageIdandorigin, and receives an access token valid 60 minutes for that origin only. It sends it asAuthorization: Bearer <token>to the/iiif/read routes; the Auth 2.0 probe service of a spectrum says whether that token opens it. - Logout: opening https://manuspectrum.huma-num.fr/iiif/auth/logout in a tab (an HTTP GET, as IIIF Auth 1.0 defines it) ends every token of the session; signing out of ManuSpectrum does too. The ManuSpectrum session itself stays open.
The token only reads: it opens the /iiif/ routes and nothing else, and it is not an API credential. Tokens go only to this site and to the viewers its administrators trust; any other origin receives invalidOrigin. A Bearer token that is not a IIIF token of this site is refused.
Known limits
- HTTPS is required: the access cookie is
Secure; SameSite=None, and a browser does not keep it on a plain HTTP site. - Third-party cookies: the token frame belongs to this site inside the viewer's page. Chrome sends the cookie; Safari (Intelligent Tracking Prevention) and Firefox (Total Cookie Protection) may block it, and the viewer then keeps asking to sign in. Use Chrome, a viewer served from this site, or allow this site's cookies in the browser.
- The ManuSpectrum session cookie is
SameSite=Strict: the login window opened from another site may ask to sign in again even when another tab is already signed in. - The viewer renews its token silently while the access cookie lives: at most 8 hours, and never longer than the ManuSpectrum session.
Versions
The major version is in the path of the context (/1). Version 1 only gains optional keys; a change of meaning would be version 2, at a new path.
JSON Schema (Draft 7): https://manuspectrum.huma-num.fr/iiif/context/xy-reading/1/schema.json. JSON-LD context: https://manuspectrum.huma-num.fr/iiif/context/xy-reading/1.jsonld.
Example
{
"id": "https://manuspectrum.huma-num.fr/iiif/data/0f3a9c2d-0000-4000-8000-0000000000c7/series.csv",
"type": "Dataset",
"format": "text/csv",
"xyReading": {
"type": "XYReading",
"conformsTo": "https://manuspectrum.huma-num.fr/iiif/context/xy-reading/1",
"dialect": {
"delimiter": ",",
"headerRowCount": 1,
"encoding": "utf-8"
},
"columns": [
{
"index": 0,
"role": "x"
},
{
"index": 1,
"role": "yLeft"
}
],
"x": {
"label": {
"none": [
"Wavelength (nm)"
]
},
"reversed": false
},
"y": [
{
"axis": "left",
"label": {
"none": [
"Reflectance (0-1)"
]
}
}
],
"corrections": [],
"derivedFrom": {
"id": "https://manuspectrum.huma-num.fr/iiif/data/0f3a9c2d-0000-4000-8000-0000000000c7/raw",
"type": "Dataset",
"format": "text/csv",
"label": {
"en": [
"GRE76-FORS-0004.csv, raw file"
],
"fr": [
"GRE76-FORS-0004.csv, fichier brut"
]
},
"service": [
{
"@id": "https://manuspectrum.huma-num.fr/iiif/auth/login",
"@type": "AuthCookieService1",
"profile": "http://iiif.io/api/auth/1/login",
"label": "Sign in to ManuSpectrum",
"header": "Restricted data",
"description": "Some data of ManuSpectrum are restricted. Sign in with your ManuSpectrum account to read what it gives access to.",
"confirmLabel": "Sign in",
"failureHeader": "Not available",
"failureDescription": "Your account does not give access to these data.",
"service": [
{
"@id": "https://manuspectrum.huma-num.fr/iiif/auth/1/token",
"@type": "AuthTokenService1",
"profile": "http://iiif.io/api/auth/1/token"
},
{
"@id": "https://manuspectrum.huma-num.fr/iiif/auth/logout",
"@type": "AuthLogoutService1",
"profile": "http://iiif.io/api/auth/1/logout",
"label": "Sign out of external viewers"
}
]
},
{
"id": "https://manuspectrum.huma-num.fr/iiif/auth/2/probe/0f3a9c2d-0000-4000-8000-0000000000c7",
"type": "AuthProbeService2",
"service": [
{
"id": "https://manuspectrum.huma-num.fr/iiif/auth/login",
"type": "AuthAccessService2",
"profile": "active",
"label": {
"en": [
"Sign in to ManuSpectrum"
],
"fr": [
"Se connecter à ManuSpectrum"
]
},
"heading": {
"en": [
"Restricted data"
],
"fr": [
"Données restreintes"
]
},
"note": {
"en": [
"Sign in with your ManuSpectrum account to read what it gives access to."
],
"fr": [
"Connectez-vous avec votre compte ManuSpectrum pour lire les données auxquelles il donne accès."
]
},
"confirmLabel": {
"en": [
"Sign in"
],
"fr": [
"Se connecter"
]
},
"service": [
{
"id": "https://manuspectrum.huma-num.fr/iiif/auth/2/token",
"type": "AuthAccessTokenService2",
"errorHeading": {
"en": [
"Not available"
],
"fr": [
"Non disponible"
]
},
"errorNote": {
"en": [
"Your account does not give access to these data."
],
"fr": [
"Votre compte ne donne pas accès à ces données."
]
}
},
{
"id": "https://manuspectrum.huma-num.fr/iiif/auth/logout",
"type": "AuthLogoutService2",
"label": {
"en": [
"Sign out of external viewers"
],
"fr": [
"Se déconnecter des visionneuses externes"
]
}
}
]
}
]
}
],
"xyReading": {
"type": "XYReading",
"conformsTo": "https://manuspectrum.huma-num.fr/iiif/context/xy-reading/1",
"columns": [
{
"index": 0,
"role": "x"
},
{
"index": 1,
"role": "yLeft"
},
{
"index": 2,
"role": "reference"
}
],
"multiY": "reference-normalize",
"corrections": [
{
"type": "reference-normalize",
"expression": "(y - dark) / (reference - dark)",
"darkDefault": 0,
"epsilon": 1e-12,
"onInvalid": "drop-point"
}
]
}
}
}
}