{"action":"created","comment":{"url":"https://api.github.com/repos/mantidproject/workspace-sandbox/pulls/comments/181970803","pull_request_review_id":112687512,"id":181970803,"diff_hunk":"@@ -0,0 +1,400 @@\n+# Type-erased dataset prototype\n+\n+## Nomenclature\n+\n+This document uses the same nomenclature as `xarray` where applicable.\n+In particular:\n+\n+- `Dataset` contains *variables*.\n+  Variables can mostly be imagined as columns of a table (a previous version of this document was therefore using the term column).\n+\n+## FAQ\n+\n+1. Why not workspaces with virtual interface to provide common functionality?\n+   - Common virtual interfaces are already running into trouble with the current workspaces.\n+     With more and more generic workspace types we would not be getting anywhere.\n+\n+1. Why not with static typing of variables, i.e., similar to `std::tuple<Ts...>`?\n+   - Yields an unreasonably large number of workspace types that probably cannot be handled efficiently in terms of compile times, code size, and complete Python exports.\n+   - Does not cover cases where we require flexibility at runtime, such as for generic tables.\n+\n+1. Why not units in type?\n+   - Yields a large number of variable types that is probably too large to handle.\n+   - Requires templating all low-level client code.\n+\n+1. Why not a nested structure of table-like objects?\n+   - Apart from an easier implementation of methods for selecting certain slices from a `Dataset`, multi-level data structures do not seem to provide advantages and only increases complexity.\n+\n+1. Why not histograms as the smallest element in a `Dataset`?\n+   - Cannot handle sharing of the x-axis (bin edges) in an easy way.\n+     There current approach via copy-on-write pointers has a couple of drawbacks:\n+     - Complex histogram API.\n+     - No good way to check for shared axis.\n+     - Cumbersome client code for maintaining sharing.\n+   - Could support histograms as the smallest element if we can do without sharing the axis.\n+     - Some memory overhead.\n+     - Compute overhead if all histograms have the same axis.\n+\n+## Dataset overview\n+\n+This prototype is trying to take inspiration from `xarray` and adopts its `Dataset` type to C++ and tailors it to the needs of neutron data handling.\n+The goal is not to simply copy `xarray`, but rather an attempt to see where solutions found by `xarray` can help us to solve our problems.\n+\n+A `Dataset` as discussed here contains:\n+\n+- A number of named dimensions.\n+- A number of *variables*, i.e., vector-like data.\n+  Each variable has an associated set of dimensions.\n+  This defines the length of the variable.\n+  Scalar data (data with zero dimensions) is represented by a vector of length 1.\n+\n+As in `xarray`, the idea is to provide a number of basic operations for `Dataset`.\n+This would probably include basic arithmetic operations as well as \"shape\" operations such as slicing, extracting, and merging in one or multiple dimensions.\n+The basic operations are currently not prototyped yet.\n+\n+As discussed elsewhere, holding each variable with its concrete type is problematic.\n+Therefore, variables are type-erased.\n+For operations that are not part of the pre-defined basic set the underlying data needs to be accessed.\n+We have several options:\n+\n+1. Access individual variables, by requesting a specific variable (identified by a tag) of a certain type (optionally with a certain name).\n+   `Dataset` can then perform a lookup among its variables and cast the matching variable to the requested concrete type.\n+   - See [`test/dataset_test.cpp`](../src/type-erased-prototype/test/dataset_test.cpp) for examples.\n+1. Use some sort of view to iterate over one or more variables of concrete type.\n+   Essentially this is a convenience layer on top of option 1.) that acts as if data was stored as an array of structures.\n+   Furthermore it provides an elegant way of dealing with variables that do not share all their dimensions.\n+   - The view/iterator could iterate either all (applicable) dimensions, a specific dimensions, or all but certain dimensions, depending on the needs to the specific client code.\n+   - See [`test/dataset_iterator_test.cpp`](../src/type-erased-prototype/test/dataset_iterator_test.cpp) for examples.\n+1. Access a subset of a `Dataset` at a given axis value for a given dimension.\n+   This is basically slicing of the `Dataset`.\n+   It is still unclear how this should be handled in detail and is currently not part of the prototype.\n+   The result would be a `Dataset` (implies that a copy of the data is returned) or a view into the `Dataset`.\n+   In either case, the result would still be type-erased.\n+   For any operation that subsequently needs to convert to concrete variable types, this access mode is thus too inefficient if the dimension used for slicing is large, such as for spectrum numbers.\n+\n+As described in this document, `Dataset` should be able to replace all of our workspace types, with maybe the exception of `MDEventWorkspace`.\n+This includes not just `MatrixWorkspace` but also `TableWorkspace`, `PeaksWorkspace`, and `MDHistoWorkspace`.\n+`Dataset` would provide a uniform interface in a single type for all of these.\n+Furthermore, `Dataset` will cover many other cases that are currently impossible to represent in a single workspace.\n+\n+## Details and discussion\n+\n+- Probably copy-on-write-wrapping each variable makes sense.\n+  - Should be handled all internally, i.e., types used as variables do not need to support this on their own.\n+\n+- Given the importance of histograms in our data reduction we should provide a `Histogram` type.\n+  As discussed in the FAQ above, storing histograms in `Dataset` has disadvantages.\n+  This could be solved by having a lightweight dummy histogram variable for accessing the underlying data.\n+  `Dataset` would contain an extra variable containing a new class `Histogram` as shown in [`test/histogram_test.cpp`](../src/type-erased-prototype/test/histogram_test.cpp).\n+  Apart from the X axis being `const` this could act very similar to our current `Histogram` class.\n+  It can be used to directly modify the data within the `Dataset`.\n+  Copying `Histogram` extracts the data into an internal buffer, such that `Histogram` can be used also stand-alone without an attached `Dataset`.\n+  - Is this reasonable?\n+  - What are the major and minor drawbacks?\n+\n+- The prototype currently accesses variables and iterator elements by type.\n+  We will probably need to use a tag or ID instead:\n+\n+  ```cpp\n+  // Need to support also generic variables such as Double or String.\n+  // Cannot use enum since it will not let us specify const access.\n+  // enum class Variable { DetectorPosition, SpectrumPosition };\n+  struct Variable {\n+    struct DetectorPosition {};\n+    struct SpectrumPosition {};\n+  };\n+\n+  // Type for variable is defined at compile time.\n+  template <class Tag> struct variable_type;\n+  template <>\n+  struct variable_type<Variable::DetectorPosition> {\n+    using type = std::vector<Eigen::Vector3d>;\n+  };\n+  template <>\n+  struct variable_type<const Variable::DetectorPosition> {\n+    using type = const std::vector<Eigen::Vector3d>;\n+  };\n+  template <class Tag>\n+  using variable_type_t = typename variable_type<Tag>::type;\n+\n+  class Dataset {\n+  public:\n+    // Support const-correct access to play nicely with copy-on-write mechanism:\n+    // Dataset::get<Variable::DetectorPosition>() returns std::vector<Eigen::Vector3d> &.\n+    // Dataset::get<const Variable::DetectorPosition>() returns const std::vector<Eigen::Vector3d> &.\n+    template <class Tag>\n+    variable_type_t<Tag> &get() conditional_const;\n+  };\n+  ```\n+  Additionally access via a name will probably be provided.\n+\n+- We will need to support \"axis\" variables that are bin edges, i.e., are by 1 longer than the size of the dimension.\n+  If we iterate over all dimensions, what should the iteration for bin edges do?\n+  - Not possible?\n+  - Support iterating \"bins\", a virtual variable providing center, left edge, right edge, and width?\n+    ```cpp\n+    Dataset d {Variable::BinEdge, Variable::DataPoint};\n+    // Full iteration with no core-dimensions, i.e., we are not iterating histograms.\n+    // This should fail to compile, since the Variable::BinEdge has a different length!\n+    DatasetIterator<Variable::BinEdge, Variable::DataPoint> it(d);\n+    // Use this instead (note that Variable::Bin is a virtual variable!)\n+    DatasetIterator<Variable::Bin, Variable::DataPoint> it(d);\n+    ```\n+    We may have bin edges in more than one dimension, how do we name those variables and distinguish them (think, e.g., of transposing a workspace containing histograms, yielding a bin-edge axis for the \"Y\" axis)?\n+    - Is `Variable::BinEdge` actually a reasonable name?\n+      Should it be `Variable::TofEdge` (and `Variable::TofBin`) instead?\n+      This would imply changing variable labes if units are changed, yielding, e.g., `Variable::dSpacingEdge`.\n+      How would we handle this generically in client code accessing the edges, given that most code will not care whether it is `Tof` or `dSpace` or anything else?\n+      Would it make sense to support `Variable::Point`, `Variable::BinEdge`, and `Variable::Bin` as aliases for whatever the current unit is, e.g., `Variable::Tof`, `Variable::TofEdge`, and `Variable::TofBin`?\n+\n+- The time-of-flight axis in our workspaces can have a different length for each spectrum.\n+  This is a case that is not supported by `xarray` but we have two choices:\n+  - Do not handle time-of-flight as a dimension.\n+    This implies that the elements in our data variables would be vectors, basically the current `HistogramData::HistogramY`, etc.\n+    This does not feel like a good solution to me?\n+  - Support variables with non-constant size in a certain dimension, e.g., bin edges and counts that have a different length in the time-of-flight dimension for every point in the spectrum dimension.\n+    Without having tried, this should be possible without too much trouble (provided that we do not require to *change* the individual lengths) and would only prevent certain operations, such as selecting a time-of-flight slice.\n+    - Need a (hidden?) index variable that provides the start of data for each new histogram.\n+      Can we simply use the `Histogram` variable, given that it stores offsets to the underlying data anyway?\n+\n+- For more convenient handling of `Dataset`, it might be beneficial to combine value and error into `struct DataPoint { double value; double error; };`.\n+  This avoid difficulties related to handling two separate variables for values and errors, in particular the need to always access two variables at the same time and the need for a mechanism linking a specific value variable to its error variable.\n+  There are a couple of non-negligible disadvantages:\n+  - Changes/complicates the way of interaction with other libraries such as `numpy` and `gsl`.\n+    - Vanilla `numpy` does not appear to have good support for arrays of value/error tuples, i.e., this does not appear to be a good solution.\n+  - Would make vectorization more difficult.\n+  - Given the disadvantages of storing values and errors as `DataPoint`, we have the option to keep value and error separate in the `Dataset`, but can nevertheless provide access via `DataPoint` for convenience:\n+    ```cpp\n+    DatasetView<Variable::DataPoint> view(dataset);\n+    // Cannot get by reference, so getter returns by value\n+    DataPoint p = view[0].dataPoint();\n+    // No reference, i.e., we cannot provide assignment, use setter\n+    view[0].setDataPoint(DataPoint(value, error));\n+    ```\n+\n+- Variables that are used as an axis to index into the `Dataset` should *not* be verified on write.\n+  This has been implemented for ensuring unique spectrum numbers as part of `IndexInfo`, which was introduced as part of refactoring for supporting scanning instruments and MPI.\n+  The result was code that is probably hard to maintain, in particular since it required changes outside `IndexInfo`, in particular `ExperimentInfo`, `MatrixWorkspace`, and `ISpectrum`.\n+  - Instead, do verification lazily only when an axis is actually used for accessing the `Dataset`.\n+  - Results in some overhead (and MPI communication), but does not appear to happen too frequently and should not be an issue for performance.\n+\n+- A dimension in the `Dataset` is effectively the same as a unit.\n+  For example,\n+  - `Dimension::Tof` could be used to imply that the unit is time-of-flight microseconds, converting the unit could be done by changing the dimension label to, e.g., `Dimension::dSpacing`.\n+  - As a consequence, any operation that checks matching dimensions of variables will implicitly ensure matching units.\n+\n+- To avoid a fair number of complications, variables should ideally not contain any data apart from the individual items.\n+  If they do, the operations on single items must probably rely on certain assumptions?\n+\n+- Mantid currently does not handle units for variables such as Y and E in our current Mantid nomenclature, with a partial exception:\n+  Distinguishing between \"histogram data\" and \"distribution data\", which is effectively the difference between a dimensionless quantity (counts) and the dimensionful frequency (unit is 1/x-unit).\n+  Handling units for Y and E would allow us to:\n+  - Get rid of the distinction between histogram data distribution data.\n+  - Provide a way to distinguish standard deviations and variances.\n+  - Allow more general operations that yield different units.\n+\n+  As mentioned above, storing units in the type (using `boost::units`) is not really feasible.\n+  We must thus provide a runtime-equivalent at a higher level.\n+  The problem of having the unit at a higher level is that it can be ignored.\n+  - This is the same issue that `HistogramData::Histogram` attempted but failed to solve:\n+    At a high level `Histogram` knows that it stores standard-deviations and the API can return variances if required.\n+    However, low level access is sometimes used to square the internal error values, such that there is a mismatch between the actual content and the \"guarentee\" that `Histogram` gives.\n+    Without storing compile-time quantities this is a problem that cannot be solved, so we will have to live with it.\n+\n+  There are a couple of options for having units attached to a variable in a `Dataset`:\n+  - A variable could be a quantity, basically something like `std::pair<UnitTag, std::vector<double>>`.\n+    - Not all variables would need to have a unit, but common ones such as Y and E would.\n+  - The unit tag could be a separate variable:\n+    - Any operation on `Dataset` that wants to handle units could simply handle it separately?\n+    - Enforce unit variable to be zero-dimensional?\n+\n+  `Variable::Histogram` should link to the unit such that operations with histogram are safe.\n+  - The unit link would then handle things like preventing adding a time-of-flight histogram to a d-spacing histogram).\n+  - Operations with histograms will have only const access to the unit (since there are many histograms but just one unit in the `Dataset`), preventing in-place operation with histograms if the unit changes.\n+    However, there may just be a handful of unit-changing operations (multiplication, unit conversion, converting errors between standard deviations and variances) that would need to be implemented explicitly, so maybe this is not an issue?\n+\n+- We probably need to link variables together.\n+  For example, variables replacing `SpectrumInfo` would need a grouping variable and variables replacing `DetectorInfo`.\n+  - Store pointer to other variables?\n+  - Prevent removing variables from `Dataset` if there are any references to it from within the same `Dataset` instance.\n+  - Link value variables to their error variables and vice versa (unless stored as `DataPoint` variables, see above).\n+\n+- We should definitely investigate how `Dataset` could support better cache reuse by chaining several operations or algorithms.\n+  - At runtime or compile-time?\n+  - Do we need things like expression templates to make this work?\n+    Does not play nicely with `auto`.\n+  - Is it worth the effort, given that we may often be limited by I/O?\n+  - Probably not too hard to implement for anything that can operate with a wrapper of a fixed signature.\n+\n+- For variables that do not explicitly store their data (such as variables from `SpectrumInfo`, which compute them based on items in variables from `DetectorInfo`) returning a reference to individual items from the iterators/views is not possible.\n+  - For `const` access we can simply return by value.\n+    Attempts to assign to a non-`const` reference will result in compilation failure, protecting us from potential bugs due to the slight interface inconsistency.\n+  - Non-`const` access is not possible in this way so we need to provide a different solution.\n+    However, this case is quite rare and should therefore not be a show stopper.\n+    Currently the only example we are aware of is masking in `SpectrumInfo`, which currently masks all associated detectors.\n+\n+## Example\n+\n+A typical `Dataset`, equivalent to one of our current workspaces could contain the following variables and dimensions:\n+\n+- Experiment logs and sample with (typically) no attached dimension.\n+- `Dimension::Detector`, applies to variables `DetectorInfo` (or an equivalent representation based on individual independent variables for positions, rotations, ...) and `DetectorIDs`.\n+- `Dimension::ScanIndex`, for scanning instrument (sync scan only), applies to `Position` and `Rotation` variables (currently part of `DetectorInfo`) and `ScanIntervals`.\n+- `Dimension::Spectrum`, applies to all variables that depend on the spectrum (but not the detector). Key examples are `SpectrumNumbers`, `SpectrumDefinitions` (mapping from spectrum to one or multiple detectors), `SpectrumInfo` (or an equivalent representation based in individual independent variables for positions, rotations, ...), `EventLists`, and histogrammed data.\n+- `Dimension::Tof`, applies mainly to variables X, Y, and E of histogrammed data, but see also discussion above regarding variable-length histograms (`Tof` is probably a bad name since it may be anything derived from it, but see discussion on units above).\n+- Multiple masking could be supported, e.g., for both `Dimension::Detector` to mask detectors as well as for `Dimension::Spectrum` and `Dimension::Tof` for masking (bins of) spectra.\n+  - Should we have first-class masking support, i.e., as a feature built into `Dataset` that is handled automatically in many cases?\n+    It is not really clear what this means.\n+  - Reversible masking has been requested.\n+    Can achieve that by taking into account masking variables, e.g., when plotting or fitting data.\n+    Only certain operations operate in a way that makes masking irreversible.\n+    They key example is `Rebin`, which, when given a `Dataset` containing `Histogram` and `BinMask` variables, could return a `Dataset` without masking since it was irreversibly absorbed into the data.\n+\n+## Interface mock-up\n+\n+Naming is just for illustration, may be very different in the actual implementation.\n+\n+```cpp\n+Dataset d;\n+\n+// Imagine arbitrary initialization here\n+\n+// Variables can be added (or removed) at any time.","path":"doc/type-erased-prototype.md","position":262,"original_position":262,"commit_id":"82b1dca88a99d77efe78c8eb5f9d532e5da28ebf","original_commit_id":"82b1dca88a99d77efe78c8eb5f9d532e5da28ebf","user":{"login":"SimonHeybrock","id":12912489,"avatar_url":"https://avatars1.githubusercontent.com/u/12912489?v=4","gravatar_id":"","url":"https://api.github.com/users/SimonHeybrock","html_url":"https://github.com/SimonHeybrock","followers_url":"https://api.github.com/users/SimonHeybrock/followers","following_url":"https://api.github.com/users/SimonHeybrock/following{/other_user}","gists_url":"https://api.github.com/users/SimonHeybrock/gists{/gist_id}","starred_url":"https://api.github.com/users/SimonHeybrock/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SimonHeybrock/subscriptions","organizations_url":"https://api.github.com/users/SimonHeybrock/orgs","repos_url":"https://api.github.com/users/SimonHeybrock/repos","events_url":"https://api.github.com/users/SimonHeybrock/events{/privacy}","received_events_url":"https://api.github.com/users/SimonHeybrock/received_events","type":"User","site_admin":false},"body":"Yes, on the one hand complete factory methods for \"standard\" datasets. Additionally there could be helpers for standard components.\r\n```cpp\r\n/// Add all variables for instrument, including those replacing DetectorInfo, SpectrumInfo, and spectrum-detector mapping.\r\nvoid addInstrument(Dataset &d);\r\n/// Add Variable::Value, Variable::Error, Variable::Histogram\r\nvoid addHistogram(Dataset &d, const std::string &name);\r\n```","created_at":"2018-04-17T07:07:57Z","updated_at":"2018-04-17T07:07:57Z","html_url":"https://github.com/mantidproject/workspace-sandbox/pull/3#discussion_r181970803","pull_request_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/pulls/3","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/mantidproject/workspace-sandbox/pulls/comments/181970803"},"html":{"href":"https://github.com/mantidproject/workspace-sandbox/pull/3#discussion_r181970803"},"pull_request":{"href":"https://api.github.com/repos/mantidproject/workspace-sandbox/pulls/3"}},"in_reply_to_id":181787737},"pull_request":{"url":"https://api.github.com/repos/mantidproject/workspace-sandbox/pulls/3","id":177979555,"html_url":"https://github.com/mantidproject/workspace-sandbox/pull/3","diff_url":"https://github.com/mantidproject/workspace-sandbox/pull/3.diff","patch_url":"https://github.com/mantidproject/workspace-sandbox/pull/3.patch","issue_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/issues/3","number":3,"state":"open","locked":false,"title":"Type erased prototype","user":{"login":"SimonHeybrock","id":12912489,"avatar_url":"https://avatars1.githubusercontent.com/u/12912489?v=4","gravatar_id":"","url":"https://api.github.com/users/SimonHeybrock","html_url":"https://github.com/SimonHeybrock","followers_url":"https://api.github.com/users/SimonHeybrock/followers","following_url":"https://api.github.com/users/SimonHeybrock/following{/other_user}","gists_url":"https://api.github.com/users/SimonHeybrock/gists{/gist_id}","starred_url":"https://api.github.com/users/SimonHeybrock/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SimonHeybrock/subscriptions","organizations_url":"https://api.github.com/users/SimonHeybrock/orgs","repos_url":"https://api.github.com/users/SimonHeybrock/repos","events_url":"https://api.github.com/users/SimonHeybrock/events{/privacy}","received_events_url":"https://api.github.com/users/SimonHeybrock/received_events","type":"User","site_admin":false},"body":"","created_at":"2018-03-28T09:31:29Z","updated_at":"2018-04-17T07:07:57Z","closed_at":null,"merged_at":null,"merge_commit_sha":"28cb09cd933179b533ef9062ae282155505a8c01","assignee":{"login":"OwenArnold","id":1109536,"avatar_url":"https://avatars3.githubusercontent.com/u/1109536?v=4","gravatar_id":"","url":"https://api.github.com/users/OwenArnold","html_url":"https://github.com/OwenArnold","followers_url":"https://api.github.com/users/OwenArnold/followers","following_url":"https://api.github.com/users/OwenArnold/following{/other_user}","gists_url":"https://api.github.com/users/OwenArnold/gists{/gist_id}","starred_url":"https://api.github.com/users/OwenArnold/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OwenArnold/subscriptions","organizations_url":"https://api.github.com/users/OwenArnold/orgs","repos_url":"https://api.github.com/users/OwenArnold/repos","events_url":"https://api.github.com/users/OwenArnold/events{/privacy}","received_events_url":"https://api.github.com/users/OwenArnold/received_events","type":"User","site_admin":false},"assignees":[{"login":"OwenArnold","id":1109536,"avatar_url":"https://avatars3.githubusercontent.com/u/1109536?v=4","gravatar_id":"","url":"https://api.github.com/users/OwenArnold","html_url":"https://github.com/OwenArnold","followers_url":"https://api.github.com/users/OwenArnold/followers","following_url":"https://api.github.com/users/OwenArnold/following{/other_user}","gists_url":"https://api.github.com/users/OwenArnold/gists{/gist_id}","starred_url":"https://api.github.com/users/OwenArnold/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OwenArnold/subscriptions","organizations_url":"https://api.github.com/users/OwenArnold/orgs","repos_url":"https://api.github.com/users/OwenArnold/repos","events_url":"https://api.github.com/users/OwenArnold/events{/privacy}","received_events_url":"https://api.github.com/users/OwenArnold/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/pulls/3/commits","review_comments_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/pulls/3/comments","review_comment_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/issues/3/comments","statuses_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/statuses/82b1dca88a99d77efe78c8eb5f9d532e5da28ebf","head":{"label":"mantidproject:type-erased-prototype","ref":"type-erased-prototype","sha":"82b1dca88a99d77efe78c8eb5f9d532e5da28ebf","user":{"login":"mantidproject","id":671496,"avatar_url":"https://avatars0.githubusercontent.com/u/671496?v=4","gravatar_id":"","url":"https://api.github.com/users/mantidproject","html_url":"https://github.com/mantidproject","followers_url":"https://api.github.com/users/mantidproject/followers","following_url":"https://api.github.com/users/mantidproject/following{/other_user}","gists_url":"https://api.github.com/users/mantidproject/gists{/gist_id}","starred_url":"https://api.github.com/users/mantidproject/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mantidproject/subscriptions","organizations_url":"https://api.github.com/users/mantidproject/orgs","repos_url":"https://api.github.com/users/mantidproject/repos","events_url":"https://api.github.com/users/mantidproject/events{/privacy}","received_events_url":"https://api.github.com/users/mantidproject/received_events","type":"Organization","site_admin":false},"repo":{"id":120288908,"name":"workspace-sandbox","full_name":"mantidproject/workspace-sandbox","owner":{"login":"mantidproject","id":671496,"avatar_url":"https://avatars0.githubusercontent.com/u/671496?v=4","gravatar_id":"","url":"https://api.github.com/users/mantidproject","html_url":"https://github.com/mantidproject","followers_url":"https://api.github.com/users/mantidproject/followers","following_url":"https://api.github.com/users/mantidproject/following{/other_user}","gists_url":"https://api.github.com/users/mantidproject/gists{/gist_id}","starred_url":"https://api.github.com/users/mantidproject/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mantidproject/subscriptions","organizations_url":"https://api.github.com/users/mantidproject/orgs","repos_url":"https://api.github.com/users/mantidproject/repos","events_url":"https://api.github.com/users/mantidproject/events{/privacy}","received_events_url":"https://api.github.com/users/mantidproject/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mantidproject/workspace-sandbox","description":"Sandbox for testing and prototyping related to workspace-2.0","fork":false,"url":"https://api.github.com/repos/mantidproject/workspace-sandbox","forks_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/forks","keys_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/teams","hooks_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/hooks","issue_events_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/issues/events{/number}","events_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/events","assignees_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/assignees{/user}","branches_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/branches{/branch}","tags_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/tags","blobs_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/git/refs{/sha}","trees_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/statuses/{sha}","languages_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/languages","stargazers_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/stargazers","contributors_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/contributors","subscribers_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/subscribers","subscription_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/subscription","commits_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/commits{/sha}","git_commits_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/git/commits{/sha}","comments_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/comments{/number}","issue_comment_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/issues/comments{/number}","contents_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/contents/{+path}","compare_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/merges","archive_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/downloads","issues_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/issues{/number}","pulls_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/pulls{/number}","milestones_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/milestones{/number}","notifications_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/labels{/name}","releases_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/releases{/id}","deployments_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/deployments","created_at":"2018-02-05T10:20:17Z","updated_at":"2018-04-06T14:54:10Z","pushed_at":"2018-04-13T13:04:11Z","git_url":"git://github.com/mantidproject/workspace-sandbox.git","ssh_url":"git@github.com:mantidproject/workspace-sandbox.git","clone_url":"https://github.com/mantidproject/workspace-sandbox.git","svn_url":"https://github.com/mantidproject/workspace-sandbox","homepage":null,"size":206,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":2,"license":{"key":"gpl-3.0","name":"GNU General Public License v3.0","spdx_id":"GPL-3.0","url":"https://api.github.com/licenses/gpl-3.0"},"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"base":{"label":"mantidproject:master","ref":"master","sha":"635af7a1e77ecc114419f25c3f9fb8e1f2001e60","user":{"login":"mantidproject","id":671496,"avatar_url":"https://avatars0.githubusercontent.com/u/671496?v=4","gravatar_id":"","url":"https://api.github.com/users/mantidproject","html_url":"https://github.com/mantidproject","followers_url":"https://api.github.com/users/mantidproject/followers","following_url":"https://api.github.com/users/mantidproject/following{/other_user}","gists_url":"https://api.github.com/users/mantidproject/gists{/gist_id}","starred_url":"https://api.github.com/users/mantidproject/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mantidproject/subscriptions","organizations_url":"https://api.github.com/users/mantidproject/orgs","repos_url":"https://api.github.com/users/mantidproject/repos","events_url":"https://api.github.com/users/mantidproject/events{/privacy}","received_events_url":"https://api.github.com/users/mantidproject/received_events","type":"Organization","site_admin":false},"repo":{"id":120288908,"name":"workspace-sandbox","full_name":"mantidproject/workspace-sandbox","owner":{"login":"mantidproject","id":671496,"avatar_url":"https://avatars0.githubusercontent.com/u/671496?v=4","gravatar_id":"","url":"https://api.github.com/users/mantidproject","html_url":"https://github.com/mantidproject","followers_url":"https://api.github.com/users/mantidproject/followers","following_url":"https://api.github.com/users/mantidproject/following{/other_user}","gists_url":"https://api.github.com/users/mantidproject/gists{/gist_id}","starred_url":"https://api.github.com/users/mantidproject/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mantidproject/subscriptions","organizations_url":"https://api.github.com/users/mantidproject/orgs","repos_url":"https://api.github.com/users/mantidproject/repos","events_url":"https://api.github.com/users/mantidproject/events{/privacy}","received_events_url":"https://api.github.com/users/mantidproject/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mantidproject/workspace-sandbox","description":"Sandbox for testing and prototyping related to workspace-2.0","fork":false,"url":"https://api.github.com/repos/mantidproject/workspace-sandbox","forks_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/forks","keys_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/teams","hooks_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/hooks","issue_events_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/issues/events{/number}","events_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/events","assignees_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/assignees{/user}","branches_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/branches{/branch}","tags_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/tags","blobs_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/git/refs{/sha}","trees_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/statuses/{sha}","languages_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/languages","stargazers_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/stargazers","contributors_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/contributors","subscribers_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/subscribers","subscription_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/subscription","commits_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/commits{/sha}","git_commits_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/git/commits{/sha}","comments_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/comments{/number}","issue_comment_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/issues/comments{/number}","contents_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/contents/{+path}","compare_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/merges","archive_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/downloads","issues_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/issues{/number}","pulls_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/pulls{/number}","milestones_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/milestones{/number}","notifications_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/labels{/name}","releases_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/releases{/id}","deployments_url":"https://api.github.com/repos/mantidproject/workspace-sandbox/deployments","created_at":"2018-02-05T10:20:17Z","updated_at":"2018-04-06T14:54:10Z","pushed_at":"2018-04-13T13:04:11Z","git_url":"git://github.com/mantidproject/workspace-sandbox.git","ssh_url":"git@github.com:mantidproject/workspace-sandbox.git","clone_url":"https://github.com/mantidproject/workspace-sandbox.git","svn_url":"https://github.com/mantidproject/workspace-sandbox","homepage":null,"size":206,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":2,"license":{"key":"gpl-3.0","name":"GNU General Public License v3.0","spdx_id":"GPL-3.0","url":"https://api.github.com/licenses/gpl-3.0"},"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mantidproject/workspace-sandbox/pulls/3"},"html":{"href":"https://github.com/mantidproject/workspace-sandbox/pull/3"},"issue":{"href":"https://api.github.com/repos/mantidproject/workspace-sandbox/issues/3"},"comments":{"href":"https://api.github.com/repos/mantidproject/workspace-sandbox/issues/3/comments"},"review_comments":{"href":"https://api.github.com/repos/mantidproject/workspace-sandbox/pulls/3/comments"},"review_comment":{"href":"https://api.github.com/repos/mantidproject/workspace-sandbox/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mantidproject/workspace-sandbox/pulls/3/commits"},"statuses":{"href":"https://api.github.com/repos/mantidproject/workspace-sandbox/statuses/82b1dca88a99d77efe78c8eb5f9d532e5da28ebf"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"SimonHeybrock"}}