syntax = "proto3";

package biopb.ome;

option java_package = "biopb.ome";
option java_multiple_files = true;

import "google/protobuf/timestamp.proto";

// PlateAcquisition is used to describe a single acquisition run for a plate.
// This object is used to record the set of images acquired in a single
// acquisition run. The Images for this run are linked to PlateAcquisition
// through WellSample.
//
message PlateAcquisition {

    // human readable name
    string name = 2;

    // A description for the plate acquistion.
    string description = 3;

    // Time when the first image of this acquisition was collected
    google.protobuf.Timestamp start_time = 4;

    // Time when the last image of this acquisition was collected
    google.protobuf.Timestamp end_time = 5;

    // The maximum number of fields (well samples) in any well in this
    // PlateAcquisition. This is only used to speed up user interaction by
    // stopping the reading of every well sample.    
    optional uint32 maximum_field_count = 6;

    // links to the well_samples (and thus images) collected
    repeated string well_sample_ids = 7;

    // links to the annotations
    repeated string annotation_ids = 8;

}


// WellSample is an individual image that has been captured within a Well.
//
message WellSample {

    // This is the main link to the core Image element
    string image_id = 2;

    // The X position of the field (image) within the well relative to the well
    // origin defined on the Plate. Units are set by PositionXUnit.
    optional float position_x = 3;

    // The Y position of the field (image) within the well relative to the well
    // origin defined on the Plate. Units are set by PositionYUnit.
    optional float position_y = 4;

    // NOTE: OME-XML uses enum for length unit. Here we just use string.
    string positioin_x_unit = 5;

    // NOTE: OME-XML uses enum for length unit. Here we just use string.
    string positioin_y_unit = 6;

    // The time-point at which the image started to be collected
    google.protobuf.Timestamp time_point = 7;

    // This records the order of the well samples. Each
    // index should be unique for a given plate but they do not
    // have to be sequential, there may be gaps if part of the
    // dataset is missing. In the user interface the displayed
    // value of the index will be calculated modulo the number
    // of PlateAcquisitions for the plate.
    uint32 index = 8; // required
}



// A Well is a component of the Well/Plate/Screen construct to describe
// screening applications. A Well has a number of WellSample elements that link
// to the Images collected in this well. The ReagentRef links any Reagents that
// were used in this Well. A well is part of only one Plate. The origin for the
// row and column identifiers is the top left corner of the plate starting at
// zero. i.e The top left well of a plate is index (0,0)
//
message Well {

    // Well samples in this well. We use a dictionary so that the keys (IDs) can
    // be referenced in other data structures, e.g. PlateAcquisition
    map<string, WellSample> well_samples = 2; 

    // This is the column index of the well, the origin is the top left corner
    // of the plate with the first column of cells being column zero. i.e top
    // left is (0,0) The combination of Row, Column has to be unique for each
    // well in a plate.
    uint32 column = 3;  // Required.

    // This is the row index of the well, the origin is the top left corner of
    // the plate with the first row of wells being row zero. i.e top left is
    // (0,0) The combination of Row, Column has to be unique for each well in a
    // plate.
    uint32 row = 4; // Required.

    // The ExternalIdentifier attribute may contain a reference to an external
    // database.
    string external_identifier = 5;

    // A human readable identifier for the screening status. e.g. empty,
    // positive control, negative control, control, experimental, etc.
    string type = 6;

    // A marker color used to highlight the well. The default value is solid
    // white. 
    optional uint32 color = 7;

    // references
    string reagent_id = 8;

    repeated string annotation_ids = 9;
}



// This element identifies microtiter plates within a screen. A plate can belong
// to more than one screen. The Screen(s) that a plate belongs to are specified
// by the ScreenRef element. The Plate ID and Name attributes are required. The
// Wells in a plate are numbers from the top-left corner in a grid starting at
// zero. i.e. The top-left well of a plate is index (0,0)
//
message Plate {
    enum NamingConvention {
        UNSPECIFIED = 0;
    
        // While the label type 'number' has a clear meaning the 'letter'
        // type is more complex.
    
        // If you have less than 26 values use letters A to Z.
        // Once you get more than 26 values there are several different
        // approaches in use.
        // One we have see include:
    
        // Single letter, then double letter each running A to Z, right first
        // e.g. A, B, C, ... X, Y, Z, AA, AB, AC, ... AY, AZ, BA, BB, ...
        // This is the format used by Microsoft Excel so users may be familiar with it.
        // This is the approach we use in the OMERO client applications.
    
        // CAPITALsmall, each running A to Z, small first
        // e.g. Aa, Ab, Ac, ... Ax, Ay, Az, Ba, Bb, Bc, ... By, Bz, Ca, Cb, ...
        // This is in use by some plate manufactures.
    
        // Single letter, then double letter, then triple letter, and so on
        // e.g. A, B, C, ... X, Y, Z, AA, BB, CC, ... YY, ZZ, AAA, BBB, ...
        // This has the advantage that the first 26 are the same as the standard
        // but has a problem an the labels get wider and wider leading to user
        // interface problems.
        LETTER = 1;
    
        // 1, 2, 3, ...
        NUMBER = 2;
    
    }
        
    // The Name identifies the plate to the user. It is used much like the ID,
    // and so must be unique within the document.
    //
    // If a plate name is not available when one is needed it will be
    // constructed in the following order:
    // 1. If name is available use it.
    // 2. If not use "Start time - End time" (NOTE: Not a subtraction! A string
    // representation of the two times separated by a dash.)
    // 3. If these times are not available use the Plate ID.
    string name = 2;

    // A description for the plate.
    string description = 3;

    // A textual annotation of the current state of the plate with respect to
    // the experiment work-flow; e.g.
    // 1. Seed cell: done; 2. Transfection: done;      3. Gel doc: todo.
    string status = 4;

    // The ExternalIdentifier attribute may contain a reference to an external
    // database.
    string external_identifier = 5;

    // The ColumnNamingConvention
    NamingConvention Column_naming_convention = 6;

    // The RowNamingConvention
    NamingConvention row_naming_convention = 7;

    // This defines the X position to use for the origin of the
    // fields (individual images) taken in a well. It is used
    // with the X in the WellSample to display the fields
    // in the correct position relative to each other. Each Well
    // in the plate has the same well origin. Units are set by WellOriginXUnit.
    // 
    // In the OMERO clients by convention we display the WellOrigin
    // in the center of the view.
    float well_origin_x = 8;


    // This defines the Y position to use for the origin of the
    // fields (individual images) taken in a well. It is used
    // with the Y in the WellSample to display the fields
    // in the correct position relative to each other. Each Well
    // in the plate has the same well origin.  Units are set by WellOriginYUnit.
    //
    // In the OMERO clients by convention we display the WellOrigin in the
    // center of the view.
    float well_origin_y = 9;

    // NOTE: OME-XML uses enum for length unit. Here we just use string.
    // RATIONALE: strong-typing length unit might be too restrictive.
    string well_origin_x_unit = 10;

    // NOTE: OME-XML uses enum for length unit. Here we just use string.
    string well_origin_y_unit = 11;

    // Number of rows in the plate
    // The default value (0) should be intepreted as "unspecfied"
    uint32 rows = 12;

    // Number of columns in the plate
    // The default value (0) should be intepreted as "unspecfied"
    uint32 columns = 13;

    // Collection of wells in the plate, indexed by well IDs.
    map<string, Well> wells = 14;

    // Information regarding the acquistions, indexed by PlateAcquisition IDs.
    map<string, PlateAcquisition> plate_acquisitions = 15;

    // The index of the WellSample to display as the default Field. 
    // This is marked specifically as `optional`, so 0 is distinguishable from `missing value`
    optional uint32 field_index = 17;

    // References
    repeated string annotation_ids = 18;

}