Skip to content

Breeding API

Trevor Rife edited this page Nov 30, 2023 · 3 revisions

BrAPI Java Client Object Mapping

Study

BrAPI studies are represented as fields in Field Book.

Field Objects in FB have the following members:

    private int exp_id;
    private String exp_name;
    private String exp_alias;
    private String unique_id;
    private String primary_id;
    private String secondary_id;
    private String exp_layout;
    private String exp_species;
    private String exp_sort;
    private String date_import;
    private String date_edit;
    private String date_export;
    private String count;
    private String exp_source;
    private String observation_level;

When studies are pulled from BrAPI Java Client via the GET call this mapping occurs:

  private BrapiStudyDetails mapStudy(BrAPIStudy study) {
        BrapiStudyDetails studyDetails = new BrapiStudyDetails();
        studyDetails.setStudyDbId(study.getStudyDbId());
        studyDetails.setStudyName(study.getStudyName());
        studyDetails.setCommonCropName(study.getCommonCropName());
        studyDetails.setStudyDescription(study.getStudyDescription());
        studyDetails.setStudyLocation(study.getLocationName());
        return studyDetails;
    }

In Field Book, all of the required information to navigate a field is included in the importable CSV field file. BrAPI takes a more modular approach to their data modeling, and thus also requires querying observation units. Observation units are plots, plants, etc, depending on the observation level. Traditionally, in FB they are called plots. Observation units hold attributes such as the unique identifier, which are essential for navigating in FB.

When loading a study from BrAPI, the obs. units are queried and linked with the study's studyDbId. Observation unit levels is selected in the UI, or defaults to plot.

FB primary and secondary identifiers can be loaded from BrAPI, by storing the attribute value in each obs. unit's positionX, and positionY, and the attribute name in positionXType and positionYType. X and Y types are Row and Column respectively by default.

Observation Units must have unique ids in their ObservationUnitDbId attribute, these are required by FB to navigate data

Additionally, FB loads Germplasm and ObservationUnitName attributes for other features throughout the app.

Finally when the Field Object is created and saved into FB's database this mapping occurs:

  1. the BrAPI host URL must be configured (saved and authenticated in preferences)
  2. the combination of field name and level must be unique to FB.
  3. obs. units must be present and contain unique id's (linked from the studyDbId)
FieldObject field = new FieldObject();
field.setExp_name(studyDetails.getStudyName());
field.setExp_alias(studyDetails.getStudyDbId()); <-- link to original BrAPI ID is saved in alias column
field.setExp_species(studyDetails.getCommonCropName());
field.setCount(studyDetails.getNumberOfPlots().toString());
field.setObservation_level(observationLevel);
...
field.setExp_source(brapiHostUrl)                <-- host url is saved in a exp_source column
field.setUnique_id("ObservationUnitDbId")        <-- essential that each imported plot has this attribute
field.setPrimary_id(primaryId);                  <-- positionXType
field.setSecondary_id(secondaryId);              <-- positionYType

Observation Variable

BrAPI Observation Variables are Traits in Field Book. BrAPI obs. vars. can be imported when importing a study, or imported directly from the Traits page.

private String trait;
    private String format;
    private String defaultValue;
    private String minimum;
    private String maximum;
    private String details;
    private String categories;
    private int realPosition;
    private String id;
    private Boolean visible;
    private String externalDbId;
    private String traitDataSource;
    private String additionalInfo;

    /**
     * This is a BMS specific field. This will be populated when traits are imported from
     * the BMS implementation of Brapi 2.0 GET /variables.
     */
    private List<String> observationLevelNames;

This mapping occurs from BrAPI obs. var to FB Trait

TraitObject trait = new TraitObject();
trait.setDefaultValue(var.getDefaultValue());

// Get the synonyms for easier reading. Set it as the trait name.
String synonym = var.getSynonyms().size() > 0 ? var.getSynonyms().get(0) : null;
trait.setTrait(getPrioritizedValue(synonym, var.getObservationVariableName())); //This will default to the Observation Variable Name if available.
trait.setDetails(var.getTrait().getTraitDescription());
// Get database id of external system to sync to enabled pushing through brAPI
trait.setExternalDbId(var.getObservationVariableDbId());

            // Need to set where we are getting the data from so we don't push to a different
            // external link than where the trait was retrieved from.
            if (BrAPIService.getHostUrl(context) != null) {
                trait.setTraitDataSource(BrAPIService.getHostUrl(context));
            } else {
                // return null to indicate we couldn't process the traits
                return null;
            }

       
trait.setMinimum(var.getScale().getValidValues().getMin().toString());           
trait.setMaximum(var.getScale().getValidValues().getMax().toString());
trait.setCategories(buildCategoryList(var.getScale().getValidValues().getCategories()));                
trait.setFormat(convertBrAPIDataType(var.getScale().getDataType().getBrapiValue()));
               
                

            // The BMS implementation of BrAPI 2.x Variables includes an Observation Variable with observationLevelNames metadata in the additionalInfo field.
            // This metadata helps identify the level(s) at which a variable is utilized within a study/field. The information will be utilized to filter the variables
            // based on the selected Observation Level during BrAPI Field Import, ensuring that only relevant variables will be processed.
            if (var.getAdditionalInfo() != null && var.getAdditionalInfo().has(ADDITIONAL_INFO_OBSERVATION_LEVEL_NAMES)) {
                JsonArray observationVariableNames = var.getAdditionalInfo().getAsJsonArray(ADDITIONAL_INFO_OBSERVATION_LEVEL_NAMES);
                // Convert the JsonArray to a List<String>
                Type listType = new TypeToken<List<String>>() {}.getType();
                trait.setObservationLevelNames(new Gson().fromJson(observationVariableNames, listType));
            }

            // Set some config variables in fieldbook
            trait.setVisible(true);
            trait.setRealPosition(0);

Observation

BrAPI Observations are Observations in Field Book.

 val internal_id_observation: Int by map
        val observation_unit_id: String by map
        val observation_variable_db_id: Int by map
        val observation_variable_field_book_format: String? by map
        val observation_variable_name: String? by map
        var value: String = if ("value" in map) (map["value"] ?: "NA").toString()
                        else if ("observation_variable_db_id" in map.keys) ObservationVariableDao.getTraitById(observation_variable_db_id)?.defaultValue ?: "NA"
                        else "NA"
        val observation_time_stamp: String? by map
        val collector: String? by map
        val geo_coordinates: String? = if (map.containsKey("geoCoordinates")) map["geoCoordinates"]?.toString() else null
        val study_id: String = (map["study_id"] ?: -1).toString()
        val last_synced_time: String by map
        val additional_info: String? by map
        var rep: String = if (map.containsKey("rep")) map["rep"]?.toString() ?: "1" else "1"

Images

Images captured within Field Book have the following information written to the TAG_USER_COMMENT EXIF attribute:

{
    "study": {
        "study_name": "field_sample",
        "study_alias": "field_sample",
        "study_unique_id_name": "plot_id",
        "study_primary_id_name": "row",
        "study_secondary_id_name": "plot",
        "date_import": "2017-06-15 05:32:44-0700",
        "count": 200
    },
    "observation_unit": {
        "observation_unit_db_id": "13RPN00002",
        "primary_id": "1",
        "secondary_id": "2"
    },
    "observation_variable": {
        "observation_variable_name": "Maize Height",
        "observation_variable_field_book_format": "photo",
        "default_value": "",
        "external_db_id": "variable1",
        "trait_data_source": "test-server.brapi.org",
        "observation_variable_details": "Test"
    },
    "collector": "Trevor",
    "timestamp": "2023-11-30-01-18-07"
}

Configuration

BrAPI settings are stored as shared preferences in Field-Book. The settings can modified individually, or set/shared all at once via a QR code.

Sharing settings via QR code relies on the BrAPIConfig Object, which has the following members:

    private String url;
    private String name;
    @SerializedName("v")
    private String version;
    @SerializedName("ps")
    private String pageSize;
    @SerializedName("cs")
    private String chunkSize;
    @SerializedName("st")
    private String serverTimeoutMilli;
    @SerializedName("flow")
    private String authFlow;
    @SerializedName("oidc")
    private String oidcUrl;
    @SerializedName("cat")
    private String catDisplay;

The object properties are deserialized from the following json structure

{
  "url": "https://test-server.brapi.org",
  "name": "BrAPI Test Server",
  "v": "V2",
  "ps": "50",
  "cs": "500",
  "st": "120",
  "flow": "OAuth2 Implicit Grant",
  "oidc": "https://test-server.brapi.org/.well-known/openid-configuration",
  "cat": "value"
}

which itself is decoded from a QR code.

BrAPI servers can supply their users with a QR code that follows this format to enable auto-configuration of a server-client connection with Field-Book.

Clone this wiki locally