Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion docs/api/visualdl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,13 @@
API
==========

Python API
----------

.. automodule:: visualdl
:members: LogReader, LogWriter
:members: LogReader, LogWriter

PyBind Wrapper Classes
-----------------------

.. automodule:: visualdl.core
90 changes: 77 additions & 13 deletions visualdl/logic/pybind.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,20 @@ namespace cp = visualdl::components;
CODE(double);

PYBIND11_MODULE(core, m) {
m.doc() = "C++ core of VisualDL";
m.doc() = R"pbdoc(

VisualDL uses PyBind to operate with the c++ framework. Users should use LogWriter to instantiate scalar/histogram/image writer

.. autoclass:: ScalarWriter__float
:members:

.. autoclass:: HistogramWriter__float
:members:

.. autoclass:: ImageWriter
:members:

)pbdoc";

py::class_<vs::LogReader>(m, "LogReader")
.def(py::init(
Expand Down Expand Up @@ -115,22 +128,63 @@ PYBIND11_MODULE(core, m) {
#undef ADD_SCALAR_READER

#define ADD_SCALAR_WRITER(T) \
py::class_<cp::Scalar<T>>(m, "ScalarWriter__" #T) \
py::class_<cp::Scalar<T>>(m, "ScalarWriter__" #T, R"pbdoc(
PyBind class. Must instantiate through the LogWriter.
)pbdoc") \
.def("set_caption", &cp::Scalar<T>::SetCaption) \
.def("add_record", &cp::Scalar<T>::AddRecord);
.def("add_record", &cp::Scalar<T>::AddRecord, R"pbdoc(
add a record with the step and value

:param step: This value appears at this step in the run.
:type step: integer
:param value: The scalar value to be recorded.
:type value: float
)pbdoc");
ADD_SCALAR_WRITER(int);
ADD_SCALAR_WRITER(float);
ADD_SCALAR_WRITER(double);
#undef ADD_SCALAR_WRITER

// clang-format on
py::class_<cp::Image>(m, "ImageWriter")
.def("set_caption", &cp::Image::SetCaption)
.def("start_sampling", &cp::Image::StartSampling)
.def("is_sample_taken", &cp::Image::IsSampleTaken)
.def("finish_sampling", &cp::Image::FinishSampling)
.def("set_sample", &cp::Image::SetSample)
.def("add_sample", &cp::Image::AddSample);
py::class_<cp::Image>(m, "ImageWriter", R"pbdoc(
PyBind class. Must instantiate through the LogWriter.
)pbdoc")
.def("set_caption", &cp::Image::SetCaption, R"pbdoc(
PyBind class. Must instantiate through the LogWriter.
)pbdoc")
.def("start_sampling", &cp::Image::StartSampling, R"pbdoc(
Start a sampling period, this interface will start a new reservoir sampling phase.
)pbdoc")
.def("is_sample_taken", &cp::Image::IsSampleTaken, R"pbdoc(
Will this sample be taken, this interface is introduced to reduce the cost
of copy image data, by testing whether this image will be sampled, and only
copy data when it should be sampled. In that way, most of un-sampled image
data need not be copied or processed at all.

:return: Index
:rtype: integer
)pbdoc")
.def("finish_sampling", &cp::Image::FinishSampling, R"pbdoc(
End a sampling period, it will clear all states for reservoir sampling.
)pbdoc")
.def("set_sample", &cp::Image::SetSample, R"pbdoc(
Store the image shape with the flatten image data.

:param index:
:type index: integer
:param image_shape: Image size
:type image_shape: tuple
:param image_data: Flatten image data
:type image_data: list
)pbdoc")
.def("add_sample", &cp::Image::AddSample, R"pbdoc(
A combined interface for is_sample_taken and set_sample, simpler but is less efficient.

:param image_shape: Image size
:type image_shape: tuple
:param image_data: Flatten image data
:type image_data: list
)pbdoc");

py::class_<cp::ImageReader::ImageRecord>(m, "ImageRecord")
// TODO(ChunweiYan) make these copyless.
Expand All @@ -147,9 +201,19 @@ PYBIND11_MODULE(core, m) {
.def("record", &cp::ImageReader::record)
.def("timestamp", &cp::ImageReader::timestamp);

#define ADD_HISTOGRAM_WRITER(T) \
py::class_<cp::Histogram<T>>(m, "HistogramWriter__" #T) \
.def("add_record", &cp::Histogram<T>::AddRecord);
#define ADD_HISTOGRAM_WRITER(T) \
py::class_<cp::Histogram<T>>(m, "HistogramWriter__" #T, R"pbdoc(
PyBind class. Must instantiate through the LogWriter.
)pbdoc") \
.def("add_record", &cp::Histogram<T>::AddRecord, R"pbdoc(
add a record with the step and histogram_value

:param step: This value appears at this step in the run.
:type step: integer
:param histogram_value: A flatten list of the distribution value. EX: [1, 2, 100, 2, 3, 200] will draw a histogram where
the value between 1~2 is 100 and the value between 2~3 is 200
:type histogram_value: list
)pbdoc");
ADD_FULL_TYPE_IMPL(ADD_HISTOGRAM_WRITER)
#undef ADD_HISTOGRAM_WRITER

Expand Down
10 changes: 10 additions & 0 deletions visualdl/python/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ def scalar(self, tag, type='float'):

:param tag: The scalar writer will label the data with tag
:type tag: basestring
:return: A scalar writer to handle step and value records
:rtype: ScalarWriter
"""
check_tag_name_valid(tag)
type2scalar = {
Expand All @@ -183,6 +185,12 @@ def image(self, tag, num_samples, step_cycle=1):

:param tag: The image writer will label the image with tag
:type tag: basestring
:param num_samples: how many samples to take in a step.
:type num_samples: integer
:param step_cycle: store every `step_cycle` as a record.
:type step_cycle: integer
:return: A image writer to sample images
:rtype: ImageWriter
"""
check_tag_name_valid(tag)
return self.writer.new_image(tag, num_samples, step_cycle)
Expand All @@ -194,6 +202,8 @@ def histogram(self, tag, num_buckets, type='float'):

:param tag: The histogram writer will label the data with tag
:type tag: basestring
:return: A histogram writer to record distribution
:rtype: HistogramWriter
"""
check_tag_name_valid(tag)
types = {
Expand Down