Turi Create  4.0
annotation_base.hpp
1 #ifndef TURI_ANNOTATIONS_ANNOTATION_BASE_HPP
2 #define TURI_ANNOTATIONS_ANNOTATION_BASE_HPP
3 
4 #include <map>
5 #include <memory>
6 #include <string>
7 #include <vector>
8 
9 #include <core/export.hpp>
10 
11 #include <core/data/flexible_type/flexible_type.hpp>
12 
13 #include <model_server/lib/extensions/ml_model.hpp>
14 
15 #include <core/storage/sframe_interface/unity_sarray.hpp>
16 #include <core/storage/sframe_interface/unity_sframe.hpp>
17 
18 #include "build/format/cpp/annotate.pb.h"
19 #include "build/format/cpp/data.pb.h"
20 #include "build/format/cpp/message.pb.h"
21 #include "build/format/cpp/meta.pb.h"
22 #include "build/format/cpp/progress.pb.h"
23 #include "build/format/cpp/similarity.pb.h"
24 
25 #include <visualization/annotation/utils.hpp>
26 #include <visualization/server/process_wrapper.hpp>
27 
28 namespace turi {
29 namespace annotate {
30 
31 /**
32  *
33  * Fallback
34  *
35  * If the user forgets to assign a return variable in their Python script this
36  * global will hold the last annotated sframe
37  */
38 struct EXPORT annotation_global : public ml_model_base {
39  std::shared_ptr<unity_sframe> annotation_sframe;
40 
41  std::shared_ptr<unity_sframe> get_value() { return annotation_sframe; }
42 
43  BEGIN_CLASS_MEMBER_REGISTRATION("annotation_global")
44  REGISTER_GETTER("annotation_sframe", annotation_global::get_value)
46 };
47 
48 /**
49  * Every annotation backend extends from this class. This forces the annotation
50  * api to remain consistent across all implementations. The reason the virtual
51  * methods exist rather than a switch statement in the annotate method is to
52  * expose this functionality to the capi so that other developers have the
53  * ability to tie their own annotations UI's to use this api.
54  */
55 class EXPORT AnnotationBase : public ml_model_base {
56 public:
57  AnnotationBase(){};
58  AnnotationBase(const std::shared_ptr<unity_sframe> &data,
59  const std::vector<std::string> &data_columns,
60  const std::string &annotation_column);
61 
62  virtual ~AnnotationBase(){};
63 
64  void annotate(const std::string &path_to_client);
65 
66  size_t size();
67 
68  std::shared_ptr<unity_sframe> returnAnnotations(bool drop_null = false);
69 
70  std::shared_ptr<annotation_global> get_annotation_registry();
71 
72  virtual annotate_spec::MetaData metaData() = 0;
73 
74  virtual annotate_spec::Data getItems(size_t start, size_t end) = 0;
75 
76  virtual annotate_spec::Annotations getAnnotations(size_t start,
77  size_t end) = 0;
78 
79  virtual bool
80  setAnnotations(const annotate_spec::Annotations &annotations) = 0;
81 
82  virtual annotate_spec::Similarity get_similar_items(size_t index,
83  size_t k = 7) = 0;
84 
85  virtual void cast_annotations() = 0;
86 
87  virtual void background_work() = 0;
88 
89  virtual void addAnnotationColumn() = 0;
90 
91  virtual void checkDataSet() = 0;
92 
94 
96 
97  REGISTER_NAMED_CLASS_MEMBER_FUNCTION("annotate", AnnotationBase::annotate,
98  "path_to_client");
99 
100  REGISTER_NAMED_CLASS_MEMBER_FUNCTION("returnAnnotations",
101  AnnotationBase::returnAnnotations,
102  "drop_null");
103  register_defaults("returnAnnotations", {{"drop_null", false}});
104 
105  REGISTER_NAMED_CLASS_MEMBER_FUNCTION("get_annotation_registry",
106  AnnotationBase::get_annotation_registry);
107 
108  // TODO: Potentially plumb `::google::protobuf::MessageLite` to variant
109  // type.
110 
112 
113 protected:
114  std::shared_ptr<unity_sframe> m_data;
115  std::shared_ptr<unity_sframe> m_data_na;
116  const std::vector<std::string> m_data_columns;
117  std::string m_annotation_column;
118  std::shared_ptr<visualization::process_wrapper> m_aw;
119 
120  void _addIndexColumn();
121  void _reshapeIndicies(size_t &start, size_t &end);
122  void _sendProgress(double value);
123 
124  /* A little trick to overload the `__serialize_proto` function at compile time
125  * so I don't have to define that for every Annotation::Specification type.
126  *
127  * Using the SFINAE method: https://en.cppreference.com/w/cpp/language/sfinae
128  */
129  template <typename T, typename = typename std::enable_if<std::is_base_of<
130  ::google::protobuf::MessageLite, T>::value>::type>
131  std::string _serialize_proto(T message);
132 
133  /*
134  * split data set into 2 parts: non-missing values and missing values
135  * */
136  void _splitUndefined(const std::string& column_names, bool how, bool recursive);
137 
138 private:
139  std::string __parse_proto_and_respond(std::string &input);
140 };
141 
142 } // namespace annotate
143 } // namespace turi
144 
145 #endif
#define BEGIN_CLASS_MEMBER_REGISTRATION(python_facing_classname)
#define BEGIN_BASE_CLASS_MEMBER_REGISTRATION()
#define IMPORT_BASE_CLASS_REGISTRATION(base_class)
#define END_CLASS_MEMBER_REGISTRATION
#define REGISTER_GETTER(propname, function)
#define REGISTER_NAMED_CLASS_MEMBER_FUNCTION(name, function,...)