This page describes Native Code Plugins for Android.
To build a plugin for Android, you should first obtain the Android NDK and familiarize yourself with the steps involved in building a shared library.
If you are using C++ (.cpp) to implement the plugin you must ensure the functions are declared with C linkage to avoid name mangling issues.
extern "C" {
float FooPluginFunction ();
}
Once built, the shared library should be copied to the Assets->Plugins->Android folder. Unity will then find it by name when you define a function like the following in the C# script:-
[DllImport ("PluginName")]
private static extern float FooPluginFunction ();
Please note that PluginName should not include the prefix (‘lib’) nor the extension (‘.so’) of the filename. You should wrap all native code methods with an additional C# code layer. This code should check Application.platform and call native methods only when the app is running on the actual device; dummy values can be returned from the C# code when running in the Editor. You can also use platform defines to control platform dependent code compilation.
You can drop pre-compiled Android library projects into the Assets->Plugins->Android folder. Pre-compiled means all .java files must have been compiled into jar files located in either the bin/ or the libs/ folder of the project. AndroidManifest.xml from these folders will get automatically merged with the main manifest file when the project is built.
See Android Library Projects for more details.
For cross platform deployment, your project should include plugins for each supported platform (ie, libPlugin.so for Android, Plugin.bundle for Mac and Plugin.dll for Windows). Unity automatically picks the right plugin for the target platform and includes it with the player.
For specific Android platform (armv7, x86), the libraries (lib*.so) should be placed in the following:
Assets/Plugins/Android/libs/x86/
Assets/Plugins/Android/libs/armeabi-v7a/
The Android plugin mechanism also allows Java to be used to enable interaction with the Android OS.
There are several ways to create a Java plugin but the result in each case is that you end up with a .jar file containing the .class files for your plugin. One approach is to download the JDK, then compile your .java files from the command line with javac. This will create .class files which you can then package into a .jar with the jar command line tool. Another option is to use the Eclipse IDE together with the ADT.
Note: Unity expects Java plugins to be built using JDK v1.6. If you are using v1.7, you should include “-source 1.6 -target 1.6” in the command line options to the compiler.
Once you have built your Java plugin (.jar) you should copy it to the Assets->Plugins->Android folder in the Unity project. Unity will package your .class files together with the rest of the Java code and then access the code using the Java Native Interface (JNI). JNI is used both when calling native code from Java and when interacting with Java (or the JavaVM) from native code.
To find your Java code from the native side you need access to the Java VM. Fortunately, that access can be obtained easily by adding a function like this to your C/C++ code:
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* jni_env = 0;
vm->AttachCurrentThread(&jni_env, 0);
return JNI_VERSION_1_6;
}
This is all that is needed to start using Java from C/C++. It is beyond the scope of this document to explain JNI completely. However, using it usually involves finding the class definition, resolving the constructor (<init>) method and creating a new object instance, as shown in this example:-
jobject createJavaObject(JNIEnv* jni_env) {
jclass cls_JavaClass = jni_env->FindClass("com/your/java/Class"); // find class definition
jmethodID mid_JavaClass = jni_env->GetMethodID (cls_JavaClass, "<init>", "()V"); // find constructor method
jobject obj_JavaClass = jni_env->NewObject(cls_JavaClass, mid_JavaClass); // create object instance
return jni_env->NewGlobalRef(obj_JavaClass); // return object with a global reference
}
AndroidJNIHelper and AndroidJNI can be used to ease some of the pain with raw JNI.
AndroidJavaObject and AndroidJavaClass automate a lot of tasks and also use cacheing to make calls to Java faster. The combination of AndroidJavaObject and AndroidJavaClass builds on top of AndroidJNI and AndroidJNIHelper, but also has a lot of logic in its own right (to handle the automation). These classes also come in a ‘static’ version to access static members of Java classes.
You can choose whichever approach you prefer, be it raw JNI through AndroidJNI class methods, or AndroidJNIHelper together with AndroidJNI and eventually AndroidJavaObject/AndroidJavaClass for maximum automation and convenience.
UnityEngine.AndroidJNI is a wrapper for the JNI calls available in C (as described above). All methods in this class are static and have a 1:1 mapping to the Java Native Interface. UnityEngine.AndroidJNIHelper provides helper functionality used by the next level, but is exposed as public methods because they may be useful for some special cases.
Instances of UnityEngine.AndroidJavaObject and UnityEngine.AndroidJavaClass have a one-to-one mapping to an instance of java.lang.Object and java.lang.Class (or subclasses thereof) on the Java side, respectively. They essentially provide 3 types of interaction with the Java side:-
The Call is separated into two categories: Call to a ‘void’ method, and Call to a method with non-void return type. A generic type is used to represent the return type of those methods which return a non-void type. The Get and Set always take a generic type representing the field type.
//The comments describe what you would need to do if you were using raw JNI
AndroidJavaObject jo = new AndroidJavaObject("java.lang.String", "some_string");
// jni.FindClass("java.lang.String");
// jni.GetMethodID(classID, "<init>", "(Ljava/lang/String;)V");
// jni.NewStringUTF("some_string");
// jni.NewObject(classID, methodID, javaString);
int hash = jo.Call<int>("hashCode");
// jni.GetMethodID(classID, "hashCode", "()I");
// jni.CallIntMethod(objectID, methodID);
Here, we’re creating an instance of java.lang.String, initialized with a string of our choice and retrieving the hash value for that string.
The AndroidJavaObject constructor takes at least one parameter, the name of class for which we want to construct an instance. Any parameters after the class name are for the constructor call on the object, in this case the string “some_string”. The subsequent Call to hashCode() returns an ‘int’ which is why we use that as the generic type parameter to the Call method.
Note: You cannot instantiate a nested Java class using dotted notation. Inner classes must use the $ separator, and it should work in both dotted and slashed format. So \[android.view.ViewGroup$LayoutParams __or__ android/view/ViewGroup$LayoutParams__ can be used, where a __LayoutParams__ class is nested in a __ViewGroup\] class.
One of the plugin samples above shows how to get the cache directory for the current application. This is how you would do the same thing from C# without any plugins:-
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
// jni.FindClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
// jni.GetStaticFieldID(classID, "Ljava/lang/Object;");
// jni.GetStaticObjectField(classID, fieldID);
// jni.FindClass("java.lang.Object");
Debug.Log(jo.Call<AndroidJavaObject>("getCacheDir").Call<string>("getCanonicalPath"));
// jni.GetMethodID(classID, "getCacheDir", "()Ljava/io/File;"); // or any baseclass thereof!
// jni.CallObjectMethod(objectID, methodID);
// jni.FindClass("java.io.File");
// jni.GetMethodID(classID, "getCanonicalPath", "()Ljava/lang/String;");
// jni.CallObjectMethod(objectID, methodID);
// jni.GetStringUTFChars(javaString);
In this case, we start with AndroidJavaClass instead of AndroidJavaObject because we want to access a static member of com.unity3d.player.UnityPlayer rather than create a new object (an instance is created automatically by the Android UnityPlayer). Then we access the static field “currentActivity” but this time we use AndroidJavaObject as the generic parameter. This is because the actual field type (android.app.Activity) is a subclass of java.lang.Object, and any non-primitive type must be accessed as AndroidJavaObject. The exceptions to this rule are strings, which can be accessed directly even though they don’t represent a primitive type in Java.
After that it is just a matter of traversing the Activity through getCacheDir() to get the File object representing the cache directory, and then calling getCanonicalPath() to get a string representation.
Of course, nowadays you don’t need to do that to get the cache directory since Unity provides access to the application’s cache and file directory with Application.temporaryCachePath and Application.persistentDataPath.
Finally, here is a trick for passing data from Java to script code using UnitySendMessage.
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour {
void Start () {
AndroidJNIHelper.debug = true;
using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) {
jc.CallStatic("UnitySendMessage", "Main Camera", "JavaMessage", "whoowhoo");
}
}
void JavaMessage(string message) {
Debug.Log("message from java: " + message);
}
}
The Java class com.unity3d.player.UnityPlayer now has a static method UnitySendMessage, equivalent to the iOS UnitySendMessage function on the native side. It can be used in Java to pass data to script code.
Here though, we call it directly from script code, which essentially relays the message on the Java side. This then calls back to the native/Unity code to deliver the message to the object named “Main Camera”. This object has a script attached which contains a method called “JavaMessage”.
As this section is mainly aimed at people who don’t have comprehensive JNI, Java and Android experience, we assume that the AndroidJavaObject/AndroidJavaClass approach has been used for interacting with Java code from Unity.
The first thing to note is that any operation you perform on an AndroidJavaObject or AndroidJavaClass is computationally expensive (as is the raw JNI approach). It is highly advisable to keep the number of transitions between managed and native/Java code to a minimum, for the sake of performance and also code clarity.
You could have a Java method to do all the actual work and then use AndroidJavaObject / AndroidJavaClass to communicate with that method and get the result. However, it is worth bearing in mind that the JNI helper classes try to cache as much data as possible to improve performance.
//The first time you call a Java function like
AndroidJavaObject jo = new AndroidJavaObject("java.lang.String", "some_string"); // somewhat expensive
int hash = jo.Call<int>("hashCode"); // first time - expensive
int hash = jo.Call<int>("hashCode"); // second time - not as expensive as we already know the java method and can call it directly
The Mono garbage collector should release all created instances of AndroidJavaObject and AndroidJavaClass after use, but it is advisable to keep them in a using(){} statement to ensure they are deleted as soon as possible. Without this, you cannot be sure when they will be destroyed. If you set AndroidJNIHelper.debug to true, you will see a record of the garbage collector’s activity in the debug output.
//Getting the system language with the safe approach
void Start () {
using (AndroidJavaClass cls = new AndroidJavaClass("java.util.Locale")) {
using(AndroidJavaObject locale = cls.CallStatic<AndroidJavaObject>("getDefault")) {
Debug.Log("current lang = " + locale.Call<string>("getDisplayLanguage"));
}
}
}
You can also call the .Dispose() method directly to ensure there are no Java objects lingering. The actual C# object might live a bit longer, but will be garbage collected by mono eventually.
With Unity Android it is possible to extend the standard UnityPlayerActivity class (the primary Java class for the Unity Player on Android, similar to AppController.mm on Unity iOS).
An application can override any and all of the basic interaction between Android OS and Unity Android. You can enable this by creating a new Activity which derives from UnityPlayerActivity (UnityPlayerActivity.java can be found at /Applications/Unity/Unity.app/Contents/PlaybackEngines/AndroidPlayer/src/com/unity3d/player on Mac and usually at C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\src\com\unity3d\player on Windows).
To do this, first locate the classes.jar shipped with Unity Android. It is found in the installation folder (usually C:\Program Files\Unity\Editor\Data (on Windows) or /Applications/Unity (on Mac)) in a sub-folder called PlaybackEngines/AndroidPlayer/Variations/mono or il2cpp/Development or Release/Classes/. Then add classes.jar to the classpath used to compile the new Activity. The resulting .class file(s) should be compressed into a .jar file and placed in the Assets->Plugins->Android folder. Since the manifest dictates which activity to launch it is also necessary to create a new AndroidManifest.xml. The AndroidManifest.xml file should also be placed in the Assets->Plugins->Android folder (placing a custom manifest completely overrides the default Unity Android manifest).
The new activity could look like the following example, OverrideExample.java:
package com.company.product;
import com.unity3d.player.UnityPlayerActivity;
import android.os.Bundle;
import android.util.Log;
public class OverrideExample extends UnityPlayerActivity {
protected void onCreate(Bundle savedInstanceState) {
// call UnityPlayerActivity.onCreate()
super.onCreate(savedInstanceState);
// print debug message to logcat
Log.d("OverrideActivity", "onCreate called!");
}
public void onBackPressed()
{
// instead of calling UnityPlayerActivity.onBackPressed() we just ignore the back button event
// super.onBackPressed();
}
}
And this is what the corresponding AndroidManifest.xml would look like:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.company.product">
<application android:icon="@drawable/app_icon" android:label="@string/app_name">
<activity android:name=".OverrideExample"
android:label="@string/app_name"
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
It is also possible to create your own subclass of UnityPlayerNativeActivity
. This has much the same effect as subclassing UnityPlayerActivity
, but with improved input latency. Because touch/motion events are processed in native code, Java views do normally not see those events. There is, however, a forwarding mechanism in Unity which allows events to be propagated to the DalvikVM. To access this mechanism, you need to modify the manifest file as follows:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.company.product">
<application android:icon="@drawable/app_icon" android:label="@string/app_name">
<activity android:name=".OverrideExampleNative"
android:label="@string/app_name"
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">
<meta-data android:name="android.app.lib_name" android:value="unity" />
<meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="true" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Note the “.OverrideExampleNative” attribute in the activity element and the two additional meta-data elements. The first meta-data is an instruction to use the Unity library libunity.so. The second enables events to be passed on to your custom subclass of UnityPlayerNativeActivity.
A simple example of the use of a native code plugin can be found here
This sample demonstrates how C code can be invoked from a Unity Android application. The package includes a scene which displays the sum of two values as calculated by the native plugin. Please note that you will need the Android NDK to compile the plugin.


1)
Aladin flew on the magic carpet.
2)
He won a first prize in the game of chess.
3)
Wendy went to see a movie with her friends.
4)
Japan is called the land of the rising sun.
5)
The Great Wall of China is really long.
6)
Farmer Frankie grows apples on his farm.
aladin
Wendy
Japan
The Great Wall
china
frankie
carpet
prize
game
chess
movie
friends
land
Sun
Farmer
apple


Lock.lock()
on all locks provided by the given iterable, in the order
provided by the iterable.Locks.lockAll(Iterable)
Lock.lockInterruptibly()
on all locks provided by the given iterable, in
the order provided by the iterable.Locks.lockInterruptiblyAll(Iterable)
ReadWriteLock
, providing an update lock in addition to the read lock and the write
lock.ReadWriteUpdateLock
, extending the functionality of the JDK
ReentrantReadWriteLock
with an update lock in addition to the read and write lock, supporting upgrade
from read-only operation to writing status, and downgrade again.Lock.tryLock()
on all locks provided by the given iterable, in the order
provided by the iterable.Lock.tryLock()
on all locks provided by the given iterable, in the order
provided by the iterable.Locks.tryLockAll(Iterable)
Locks.tryLockAll(long, java.util.concurrent.TimeUnit, Iterable)
Lock.unlock()
on all locks provided by the given iterable, in the
order provided by the iterable.Locks.unlockAll(Iterable)
Copyright © 2013. All Rights Reserved.


|
|
|
|
|
|
|
|
fadd(self,
xs,
sample=False)
Accumulate and return the current count. |
|
|
|
|
fjb(self,
xs=None,
sample=True,
excess=True)
Accumulate and compute the current Jarque-Bera normality. |
|
|
|
|
fjb_(self,
*xs,
**sample_excess)
Accumulate and compute the current Jarque-Bera normality. |
|
|
|
|
fkurtosis(self,
xs=None,
sample=False,
excess=True)
Accumulate and return the current kurtosis. |
|
|
|
|
fkurtosis_(self,
*xs,
**sample_excess)
Accumulate and return the current kurtosis. |
|
|
|
|
fmedian(self,
xs=None)
Accumulate and return the current median. |
|
|
|
|
fmedian_(self,
*xs)
Accumulate and return the current median. |
|
|
|
|
fskewness(self,
xs=None,
sample=False)
Accumulate and return the current skewness. |
|
|
|
|
fskewness_(self,
*xs,
**sample)
Accumulate and return the current skewness. |
|
|
|
|
toFwelford(self,
name='')
Return an Fwelford equivalent. |
|
|
|
Inherited from _FstatsBase :
fadd_ ,
fmean ,
fmean_ ,
fstdev ,
fstdev_ ,
fvariance ,
fvariance_
Inherited from _FstatsNamed :
__add__ ,
__float__ ,
__int__ ,
__len__ ,
__neg__ ,
__radd__ ,
__str__ ,
copy ,
fcopy
Inherited from named._Named :
__imatmul__ ,
__matmul__ ,
__repr__ ,
__rmatmul__ ,
attrs ,
classof ,
dup ,
methodname ,
rename ,
toRepr ,
toStr ,
toStr2
Inherited from object :
__delattr__ ,
__format__ ,
__getattribute__ ,
__hash__ ,
__new__ ,
__reduce__ ,
__reduce_ex__ ,
__setattr__ ,
__sizeof__ ,
__subclasshook__
|


Are there plans to allow for multiple emonTx to be monitoried through a single emonBase unit?
I currently want to monitor 3 or 4 power points but they are located some distance from each other.
I've seen (overpriced) commercial units that will allow 3 separate monitor points via a single controller.E
EDIT: OK a bit more reading has answered my question :-)
Re: Monitoring multiple emonTx units
Yes, it's possible. Just set the emonTx's to all be on the same frequency, network with individual node ID's. Then tell the emonBase to separate out the wireless data from the separate emonTx's
We have an emonBase example using the EtherShield library, this library in no longer supported. We have moved to using the EtherCard (see latest NanodeRF github examples), it shouldn't be too difficult to move the example to use the EtherCard library. https://github.com/openenergymonitor/NanodeRF_ethershield/tree/master/nanodeRF_recieve_multiple_emontx
The code example is just a quick demo and could be improved. It would be great to get a page on the website detailing how more than emonTx can be used with a single emonBase. We would be very graceful if in the future maybe you could write such a page.
Re: Monitoring multiple emonTx units
Im using one Base to read from 3 TX's.
First is for Elect PV generated, second is for Import/Export, third is for water/gas.
Im using the multi Pachube/EmonCMS sketch provided by by Francois which solved my Pachube posting issues, documented in thread: http://www.openenergymonitor.org/emon/node/376
The bits I changed to cope with with multiple TX's are basically to make sure each TX has a different node ID.
Then in the Base code, ensure you have code to extract the node ID from the RF:
byte emontx_nodeID=rf12_hdr & 0x1F;
Finally, in your main processing code, use logic to do what you want based on the nodeID being sent:
Re: Monitoring multiple emonTx units
Hi, I would also like to build monitor with multi emontx towards on single emonbase. I currently have two emontx and one NanodeRF but no luck adapting the standard NanodeRF_Power_RTCrelay_GLCDtemp yet. The code will work with either emonTx node id 10 or 11 individually defined in // 1 on receive . I think my problem is blue colored code: Thanks in advance
All suggestions welcome:
if (rf12_recvDone()){
if (rf12_crc == 0 && (rf12_hdr & RF12_HDR_CTL) == 0)
{
int node_id = (rf12_hdr & 0x1F);
if (node_id == 10) // EMONTX
{
emontx = *(PayloadTX*) rf12_data; // get emontx data
Serial.println(); // print emontx data to serial
Serial.print("1 emontx packet rx");
last_rf = millis(); // reset lastRF timer
delay(50); // make sure serial printing finished
// JSON creation: JSON sent are of the format: {key1:value1,key2:value2} and so on
str.reset(); // Reset json string
str.print("{rf_fail:0"); // RF recieved so no failure
str.print(",power1:"); str.print(emontx.power1); // Add power reading
str.print(",power2:"); str.print(emontx.power2); // Add power reading
str.print(",power3:"); str.print(emontx.power3); // Add power reading
str.print(",voltage:"); str.print(emontx.voltage); // Add emontx battery voltage reading
data_ready = 1; // data is ready
rf_error = 0;
}
if (node_id == 11) // second EMONTX
{
emontx2 = *(PayloadTX2*) rf12_data; // get second emontx2 data
Serial.println(); // print second emontx2 data to serial
Serial.print("2 emontx2 packet rx");
last_rf = millis(); // reset lastRF timer
delay(50); // make sure serial printing finished
// JSON creation: JSON sent are of the format: {key1:value1,key2:value2} and so on
str.reset(); // Reset json string
str.print("{rf_fail:0"); // RF recieved so no failure
str.print(",power11:"); str.print(emontx2.power11); // Add power reading
str.print(",power12:"); str.print(emontx2.power12); // Add power reading
str.print(",power13:"); str.print(emontx2.power13); // Add power reading
str.print(",powerFactor:"); str.print(emontx2.powerFactor); // Add emontx powerFactor reading
str.print(",MainsVoltage:"); str.print(emontx2.Vrms); // Add emontx mainvoltage reading
data2_ready = 1; // data2 is ready
rf_error = 0;
}
if (node_id == 20) // EMONGLCD
{
emonglcd = *(PayloadGLCD*) rf12_data; // get emonglcd data
Serial.print("5 emonglcd: "); // print output
Serial.println(emonglcd.temperature);
emonglcd_rx = 1;
}
}
}
Re: Monitoring multiple emonTx units
Hi Peter,
What you have posted looks like it should work, please post up the whole sketch, it would be good to check what you have at the beginning and in setup.
Re: Monitoring multiple emonTx units
It's works in part for two emontxs nodes when certain code was omitted e.g. // code is inserted to remove the one line of code for emontx2 nodeid 11 see attached file in the section title "// 1) On RF receive" . Search "change peter" to see my changes elsewhere in the basic template.
Once I activated " //str.print(",MainsV:"); str.print(emontx2.Vrms); " line of code for emontx2 by removing the // the result in emoncms was inputs rf_fail =1 and com port output was blank. I tried block another line of code in str.print for emontx2 and open this one (no luck) just to prove it wasn't due to the number of lines of str.print, it seems to be this one line of code mentioned above causing issue.
Another problem I observed seems to be the delay in getting feeds or updates when second emontx2 was added, seems to my untrained eye that there may be some congestion or overlap. I will monitor the number of rf_fails and other data towards cms.
My emoncms is quiet a mess now with many unused inputs etc. is there an easy way to reset all data or should I just change to new database.
Code attached for emontx and emonbase.
Thanks for support.
Cheers
Peter
P.S. Hope I'm clear above


| dc:title | Key/Encoded-Value Metadata Format for Canonical Citations |
|---|---|
| dc:creator | Cornell University Library |
| dc:description | This Matrix represents the Canonical Citation Format as a string of ampersand-delimited Key/Encoded Value pairs |
| dc:identifier | http://cwkb.org/docs/matrix |
| dc:identifier | info:ofi/fmt:kev:mtx:canonical_cit |
| dcterms:created | 2010-09-22 |
| dcterms:modified | 2011-08-17 |
A representation of a Key/Encoded-Value pair is generated by concatenating the contents of the first four columns of a row that begins with an ampersand in the Matrix below. The ordering of KEV pairs is not important. Rows which have '#' in the first column are comments and should not be included in the representation.
The following data types are provided for the values of the Keys, which must be URL-encoded:
| <data> | Character string |
|---|---|
| <id> | Character string for an Identifier (Z39.88-2004, Part 1, Section 7) |
| <fmt-id> | Character string for a Format Identifier (Z39.88-2004, Part 1, Sections 12 and 13) |
| <m-key> | Character string for a Metadata Key (Z39.88-2004, Part 2, Section 7.1) |
| <url> | Character string for a URL |
| <date> | Character string representing a date to the complete date level of the W3CDTF profile of ISO 8601, of the form: [ YYYY-MM-DD | YYYY-MM | YYYY ] |
| <time> | Character string representing a date and time to the seconds level of the W3CDTF profile of ISO 8601, of the form: [ YYYY-MM-DDThh:mm:ssTZD | YYYY-MM-DD ] |
Abbreviations in column headings:
| Delim | Key | Equals | Value | Min | Max | Description |
|---|---|---|---|---|---|---|
| & | workid | = | <data> | 0 | * | An identifier for the work. Best practice is to use an HTTP URI identifier. |
| & | aulast | = | <data> | 0 | 1 | First author's family name. Use when available or appropriate (modern names with distinguishable given and family names). William Shakespeare is recorded as "aulast=Shakespeare". |
| & | aufirst | = | <data> | 0 | 1 | First author's given name or names or initials. Use when available or appropriate (modern names with distinguishable given and family names). William Shakespeare is recorded as "aufirst=William". |
| & | au | = | <data> | 0 | 1 | First author's full name. Use for pre-modern names or when unable to distinguish given and family names. For example, "au=Ovid". |
| & | auauthority | = | <data> | 0 | 1 | An authoritative form of the first author's name. For example, "auauthority=Shakespeare, William, 1564-1616". If used, auscheme should be provided. |
| & | auscheme | = | <url> | 0 | 1 | An HTTP URI that identifies the source of the authoritative form of the author's name. For example, "auscheme=http://authorities.loc.gov/". |
| & | title | = | <data> | 0 | 1 | The title of the work. |
| & | titleauthority | = | <data> | 0 | 1 | An authoritative form of the title of the work. If used, titlescheme should be provided. |
| & | titlescheme | = | <url> | 0 | 1 | An HTTP URI that identifies the source of the authoritative form of the title of the work. |
| & | slevel1 | = | <data> | 0 | 1 | The start of the first or highest hierarchical level in the canonical citation. Homer Iliad 1.125-2.35 is recorded as "slevel1=1". |
| & | slevel2 | = | <data> | 0 | 1 | The start of the second highest hierarchical level in the canonical citation. Homer Iliad 1.125-2.35 is recorded as "slevel2=125". |
| & | slevel3 | = | <date> | 0 | 1 | The start of the third highest hierarchical level in the canonical citation. |
| & | slevel4 | = | <data> | 0 | 1 | The start of the fourth highest hierarchical level in the canonical citation. |
| & | slevel5 | = | <data> | 0 | 1 | The start of the fifth highest hierarchical level in the canonical citation. |
| & | elevel1 | = | <data> | 0 | 1 | The end of the first or highest hierarchical level in the canonical citation. If omitted, equivalent to slevel1. Homer Iliad 1.125-2.35 is recorded as "elevel1=2". |
| & | elevel2 | = | <data> | 0 | 1 | The end of the second highest hierarchical level in the canonical citation. If omitted, equivalent to slevel2. Homer Iliad 1.125-2.35 is recorded as "elevel2=35". |
| & | elevel3 | = | <data> | 0 | 1 | The end of the third highest hierarchical level in the canonical citation. If omitted, equivalent to slevel3. |
| & | elevel4 | = | <data> | 0 | 1 | The end of the fourth highest hierarchical level in the canonical citation. If omitted, equivalent to slevel4. |
| & | elevel5 | = | <data> | 0 | 1 | The end of the fifth highest hierarchical level in the canonical citation. If omitted, equivalent to slevel5. |


DATA
Hyperparameters
Dataset Statistics
Examples
Input shape
Label shape
Pixel range
MODEL
INFERENCE AND TRAIN STATS
Inference
Train