You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

serdes.cc 21 kB

4 years ago
4 years ago
4 years ago
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. /**
  2. * Copyright 2021 Huawei Technologies Co., Ltd
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <fstream>
  17. #include <stack>
  18. #include "minddata/dataset/engine/serdes.h"
  19. #include "minddata/dataset/core/pybind_support.h"
  20. #include "utils/file_utils.h"
  21. #include "utils/utils.h"
  22. namespace mindspore {
  23. namespace dataset {
  24. std::map<std::string, Status (*)(nlohmann::json json_obj, std::shared_ptr<TensorOperation> *operation)>
  25. Serdes::func_ptr_ = Serdes::InitializeFuncPtr();
  26. Status Serdes::SaveToJSON(std::shared_ptr<DatasetNode> node, const std::string &filename, nlohmann::json *out_json) {
  27. RETURN_UNEXPECTED_IF_NULL(node);
  28. RETURN_UNEXPECTED_IF_NULL(out_json);
  29. // Dump attributes of current node to json string
  30. nlohmann::json args;
  31. RETURN_IF_NOT_OK(node->to_json(&args));
  32. args["op_type"] = node->Name();
  33. // If the current node isn't leaf node, visit all its children and get all attributes
  34. std::vector<nlohmann::json> children_pipeline;
  35. if (!node->IsLeaf()) {
  36. for (auto child : node->Children()) {
  37. nlohmann::json child_args;
  38. RETURN_IF_NOT_OK(SaveToJSON(child, "", &child_args));
  39. children_pipeline.push_back(child_args);
  40. }
  41. }
  42. args["children"] = children_pipeline;
  43. // Save json string into file if filename is given.
  44. if (!filename.empty()) {
  45. RETURN_IF_NOT_OK(SaveJSONToFile(args, filename));
  46. }
  47. *out_json = args;
  48. return Status::OK();
  49. }
  50. Status Serdes::SaveJSONToFile(nlohmann::json json_string, const std::string &file_name) {
  51. try {
  52. std::optional<std::string> dir = "";
  53. std::optional<std::string> local_file_name = "";
  54. FileUtils::SplitDirAndFileName(file_name, &dir, &local_file_name);
  55. if (!dir.has_value()) {
  56. dir = ".";
  57. }
  58. auto realpath = FileUtils::GetRealPath(dir.value().data());
  59. if (!realpath.has_value()) {
  60. MS_LOG(ERROR) << "Invalid file, get real path failed, path=" << file_name;
  61. RETURN_STATUS_UNEXPECTED("Invalid file, get real path failed, path=" + file_name);
  62. }
  63. std::optional<std::string> whole_path = "";
  64. FileUtils::ConcatDirAndFileName(&realpath, &local_file_name, &whole_path);
  65. std::ofstream file(whole_path.value());
  66. file << json_string;
  67. file.close();
  68. ChangeFileMode(whole_path.value(), S_IRUSR | S_IWUSR);
  69. } catch (const std::exception &err) {
  70. RETURN_STATUS_UNEXPECTED("Invalid data, failed to save json string into file: " + file_name +
  71. ", error message: " + err.what());
  72. }
  73. return Status::OK();
  74. }
  75. Status Serdes::Deserialize(const std::string &json_filepath, std::shared_ptr<DatasetNode> *ds) {
  76. nlohmann::json json_obj;
  77. CHECK_FAIL_RETURN_UNEXPECTED(json_filepath.size() != 0, "Json path is null");
  78. std::ifstream json_in(json_filepath);
  79. CHECK_FAIL_RETURN_UNEXPECTED(json_in, "Invalid file, failed to open json file: " + json_filepath);
  80. try {
  81. json_in >> json_obj;
  82. } catch (const std::exception &e) {
  83. return Status(StatusCode::kMDSyntaxError,
  84. "Invalid file, failed to parse json file: " + json_filepath + ", error message: " + e.what());
  85. }
  86. RETURN_IF_NOT_OK(ConstructPipeline(json_obj, ds));
  87. return Status::OK();
  88. }
  89. Status Serdes::ConstructPipeline(nlohmann::json json_obj, std::shared_ptr<DatasetNode> *ds) {
  90. CHECK_FAIL_RETURN_UNEXPECTED(json_obj.find("children") != json_obj.end(), "Failed to find children");
  91. std::shared_ptr<DatasetNode> child_ds;
  92. if (json_obj["children"].size() == 0) {
  93. // If the JSON object has no child, then this node is a leaf node. Call create node to construct the corresponding
  94. // leaf node
  95. RETURN_IF_NOT_OK(CreateNode(nullptr, json_obj, ds));
  96. } else if (json_obj["children"].size() == 1) {
  97. // This node only has one child, construct the sub-tree under it first, and then call create node to construct the
  98. // corresponding node
  99. RETURN_IF_NOT_OK(ConstructPipeline(json_obj["children"][0], &child_ds));
  100. RETURN_IF_NOT_OK(CreateNode(child_ds, json_obj, ds));
  101. } else {
  102. std::vector<std::shared_ptr<DatasetNode>> datasets;
  103. for (auto child_json_obj : json_obj["children"]) {
  104. RETURN_IF_NOT_OK(ConstructPipeline(child_json_obj, &child_ds));
  105. datasets.push_back(child_ds);
  106. }
  107. if (json_obj["op_type"] == "Zip") {
  108. CHECK_FAIL_RETURN_UNEXPECTED(datasets.size() > 1, "Should zip more than 1 dataset");
  109. RETURN_IF_NOT_OK(ZipNode::from_json(datasets, ds));
  110. } else if (json_obj["op_type"] == "Concat") {
  111. CHECK_FAIL_RETURN_UNEXPECTED(datasets.size() > 1, "Should concat more than 1 dataset");
  112. RETURN_IF_NOT_OK(ConcatNode::from_json(json_obj, datasets, ds));
  113. } else {
  114. return Status(StatusCode::kMDUnexpectedError,
  115. "Invalid data, unsupported operation type: " + std::string(json_obj["op_type"]));
  116. }
  117. }
  118. return Status::OK();
  119. }
  120. Status Serdes::CreateNode(const std::shared_ptr<DatasetNode> &child_ds, nlohmann::json json_obj,
  121. std::shared_ptr<DatasetNode> *ds) {
  122. CHECK_FAIL_RETURN_UNEXPECTED(json_obj.find("op_type") != json_obj.end(), "Failed to find op_type in json.");
  123. std::string op_type = json_obj["op_type"];
  124. if (child_ds == nullptr) {
  125. // if dataset doesn't have any child, then create a source dataset IR. e.g., ImageFolderNode, CocoNode
  126. RETURN_IF_NOT_OK(CreateDatasetNode(json_obj, op_type, ds));
  127. } else {
  128. // if the dataset has at least one child, then create an operation dataset IR, e.g., BatchNode, MapNode
  129. RETURN_IF_NOT_OK(CreateDatasetOperationNode(child_ds, json_obj, op_type, ds));
  130. }
  131. return Status::OK();
  132. }
  133. Status Serdes::CreateDatasetNode(const nlohmann::json &json_obj, const std::string &op_type,
  134. std::shared_ptr<DatasetNode> *ds) {
  135. if (op_type == kAlbumNode) {
  136. RETURN_IF_NOT_OK(AlbumNode::from_json(json_obj, ds));
  137. } else if (op_type == kCelebANode) {
  138. RETURN_IF_NOT_OK(CelebANode::from_json(json_obj, ds));
  139. } else if (op_type == kCifar10Node) {
  140. RETURN_IF_NOT_OK(Cifar10Node::from_json(json_obj, ds));
  141. } else if (op_type == kCifar100Node) {
  142. RETURN_IF_NOT_OK(Cifar100Node::from_json(json_obj, ds));
  143. } else if (op_type == kCLUENode) {
  144. RETURN_IF_NOT_OK(CLUENode::from_json(json_obj, ds));
  145. } else if (op_type == kCocoNode) {
  146. RETURN_IF_NOT_OK(CocoNode::from_json(json_obj, ds));
  147. } else if (op_type == kCSVNode) {
  148. RETURN_IF_NOT_OK(CSVNode::from_json(json_obj, ds));
  149. } else if (op_type == kFlickrNode) {
  150. RETURN_IF_NOT_OK(FlickrNode::from_json(json_obj, ds));
  151. } else if (op_type == kImageFolderNode) {
  152. RETURN_IF_NOT_OK(ImageFolderNode::from_json(json_obj, ds));
  153. } else if (op_type == kManifestNode) {
  154. RETURN_IF_NOT_OK(ManifestNode::from_json(json_obj, ds));
  155. } else if (op_type == kMnistNode) {
  156. RETURN_IF_NOT_OK(MnistNode::from_json(json_obj, ds));
  157. } else if (op_type == kTextFileNode) {
  158. RETURN_IF_NOT_OK(TextFileNode::from_json(json_obj, ds));
  159. } else if (op_type == kTFRecordNode) {
  160. RETURN_IF_NOT_OK(TFRecordNode::from_json(json_obj, ds));
  161. } else if (op_type == kVOCNode) {
  162. RETURN_IF_NOT_OK(VOCNode::from_json(json_obj, ds));
  163. } else {
  164. return Status(StatusCode::kMDUnexpectedError, "Invalid data, unsupported operation type: " + op_type);
  165. }
  166. return Status::OK();
  167. }
  168. Status Serdes::CreateDatasetOperationNode(const std::shared_ptr<DatasetNode> &ds, const nlohmann::json &json_obj,
  169. const std::string &op_type, std::shared_ptr<DatasetNode> *result) {
  170. if (op_type == kBatchNode) {
  171. RETURN_IF_NOT_OK(BatchNode::from_json(json_obj, ds, result));
  172. } else if (op_type == kMapNode) {
  173. RETURN_IF_NOT_OK(MapNode::from_json(json_obj, ds, result));
  174. } else if (op_type == kProjectNode) {
  175. RETURN_IF_NOT_OK(ProjectNode::from_json(json_obj, ds, result));
  176. } else if (op_type == kRenameNode) {
  177. RETURN_IF_NOT_OK(RenameNode::from_json(json_obj, ds, result));
  178. } else if (op_type == kRepeatNode) {
  179. RETURN_IF_NOT_OK(RepeatNode::from_json(json_obj, ds, result));
  180. } else if (op_type == kShuffleNode) {
  181. RETURN_IF_NOT_OK(ShuffleNode::from_json(json_obj, ds, result));
  182. } else if (op_type == kSkipNode) {
  183. RETURN_IF_NOT_OK(SkipNode::from_json(json_obj, ds, result));
  184. } else if (op_type == kTransferNode) {
  185. RETURN_IF_NOT_OK(TransferNode::from_json(json_obj, ds, result));
  186. } else if (op_type == kTakeNode) {
  187. RETURN_IF_NOT_OK(TakeNode::from_json(json_obj, ds, result));
  188. } else {
  189. return Status(StatusCode::kMDUnexpectedError, "Invalid data, unsupported operation type: " + op_type);
  190. }
  191. return Status::OK();
  192. }
  193. Status Serdes::ConstructSampler(nlohmann::json json_obj, std::shared_ptr<SamplerObj> *sampler) {
  194. CHECK_FAIL_RETURN_UNEXPECTED(json_obj.find("num_samples") != json_obj.end(), "Failed to find num_samples");
  195. CHECK_FAIL_RETURN_UNEXPECTED(json_obj.find("sampler_name") != json_obj.end(), "Failed to find sampler_name");
  196. int64_t num_samples = json_obj["num_samples"];
  197. std::string sampler_name = json_obj["sampler_name"];
  198. if (sampler_name == "DistributedSampler") {
  199. RETURN_IF_NOT_OK(DistributedSamplerObj::from_json(json_obj, num_samples, sampler));
  200. } else if (sampler_name == "PKSampler") {
  201. RETURN_IF_NOT_OK(PKSamplerObj::from_json(json_obj, num_samples, sampler));
  202. } else if (sampler_name == "RandomSampler") {
  203. RETURN_IF_NOT_OK(RandomSamplerObj::from_json(json_obj, num_samples, sampler));
  204. } else if (sampler_name == "SequentialSampler") {
  205. RETURN_IF_NOT_OK(SequentialSamplerObj::from_json(json_obj, num_samples, sampler));
  206. } else if (sampler_name == "SubsetSampler") {
  207. RETURN_IF_NOT_OK(SubsetSamplerObj::from_json(json_obj, num_samples, sampler));
  208. } else if (sampler_name == "SubsetRandomSampler") {
  209. RETURN_IF_NOT_OK(SubsetRandomSamplerObj::from_json(json_obj, num_samples, sampler));
  210. } else if (sampler_name == "WeightedRandomSampler") {
  211. RETURN_IF_NOT_OK(WeightedRandomSamplerObj::from_json(json_obj, num_samples, sampler));
  212. } else {
  213. return Status(StatusCode::kMDUnexpectedError, "Invalid data, unsupported sampler type: " + sampler_name);
  214. }
  215. return Status::OK();
  216. }
  217. Status Serdes::ConstructTensorOps(nlohmann::json json_obj, std::vector<std::shared_ptr<TensorOperation>> *result) {
  218. std::vector<std::shared_ptr<TensorOperation>> output;
  219. for (nlohmann::json item : json_obj) {
  220. if (item.find("python_module") != item.end()) {
  221. if (Py_IsInitialized() != 0) {
  222. RETURN_IF_NOT_OK(PyFuncOp::from_json(item, result));
  223. } else {
  224. LOG_AND_RETURN_STATUS_SYNTAX_ERROR(
  225. "Python module is not initialized or Pyfunction is not supported on this platform.");
  226. }
  227. } else {
  228. CHECK_FAIL_RETURN_UNEXPECTED(item.find("tensor_op_name") != item.end(), "Failed to find tensor_op_name");
  229. CHECK_FAIL_RETURN_UNEXPECTED(item.find("tensor_op_params") != item.end(), "Failed to find tensor_op_params");
  230. std::string op_name = item["tensor_op_name"];
  231. nlohmann::json op_params = item["tensor_op_params"];
  232. std::shared_ptr<TensorOperation> operation = nullptr;
  233. CHECK_FAIL_RETURN_UNEXPECTED(func_ptr_.find(op_name) != func_ptr_.end(),
  234. "Invalid data, unsupported operation: " + op_name);
  235. RETURN_IF_NOT_OK(func_ptr_[op_name](op_params, &operation));
  236. output.push_back(operation);
  237. *result = output;
  238. }
  239. }
  240. return Status::OK();
  241. }
  242. std::map<std::string, Status (*)(nlohmann::json json_obj, std::shared_ptr<TensorOperation> *operation)>
  243. Serdes::InitializeFuncPtr() {
  244. std::map<std::string, Status (*)(nlohmann::json json_obj, std::shared_ptr<TensorOperation> * operation)> ops_ptr;
  245. ops_ptr[vision::kAdjustGammaOperation] = &(vision::AdjustGammaOperation::from_json);
  246. ops_ptr[vision::kAffineOperation] = &(vision::AffineOperation::from_json);
  247. ops_ptr[vision::kAutoContrastOperation] = &(vision::AutoContrastOperation::from_json);
  248. ops_ptr[vision::kBoundingBoxAugmentOperation] = &(vision::BoundingBoxAugmentOperation::from_json);
  249. ops_ptr[vision::kCenterCropOperation] = &(vision::CenterCropOperation::from_json);
  250. ops_ptr[vision::kCropOperation] = &(vision::CropOperation::from_json);
  251. ops_ptr[vision::kCutMixBatchOperation] = &(vision::CutMixBatchOperation::from_json);
  252. ops_ptr[vision::kCutOutOperation] = &(vision::CutOutOperation::from_json);
  253. ops_ptr[vision::kDecodeOperation] = &(vision::DecodeOperation::from_json);
  254. #ifdef ENABLE_ACL
  255. ops_ptr[vision::kDvppCropJpegOperation] = &(vision::DvppCropJpegOperation::from_json);
  256. ops_ptr[vision::kDvppDecodeResizeOperation] = &(vision::DvppDecodeResizeOperation::from_json);
  257. ops_ptr[vision::kDvppDecodeResizeCropOperation] = &(vision::DvppDecodeResizeCropOperation::from_json);
  258. ops_ptr[vision::kDvppNormalizeOperation] = &(vision::DvppNormalizeOperation::from_json);
  259. ops_ptr[vision::kDvppResizeJpegOperation] = &(vision::DvppResizeJpegOperation::from_json);
  260. #endif
  261. ops_ptr[vision::kEqualizeOperation] = &(vision::EqualizeOperation::from_json);
  262. ops_ptr[vision::kGaussianBlurOperation] = &(vision::GaussianBlurOperation::from_json);
  263. ops_ptr[vision::kHorizontalFlipOperation] = &(vision::HorizontalFlipOperation::from_json);
  264. ops_ptr[vision::kHwcToChwOperation] = &(vision::HwcToChwOperation::from_json);
  265. ops_ptr[vision::kInvertOperation] = &(vision::InvertOperation::from_json);
  266. ops_ptr[vision::kMixUpBatchOperation] = &(vision::MixUpBatchOperation::from_json);
  267. ops_ptr[vision::kNormalizeOperation] = &(vision::NormalizeOperation::from_json);
  268. ops_ptr[vision::kNormalizePadOperation] = &(vision::NormalizePadOperation::from_json);
  269. ops_ptr[vision::kPadOperation] = &(vision::PadOperation::from_json);
  270. ops_ptr[vision::kRandomAffineOperation] = &(vision::RandomAffineOperation::from_json);
  271. ops_ptr[vision::kRandomColorOperation] = &(vision::RandomColorOperation::from_json);
  272. ops_ptr[vision::kRandomColorAdjustOperation] = &(vision::RandomColorAdjustOperation::from_json);
  273. ops_ptr[vision::kRandomCropDecodeResizeOperation] = &(vision::RandomCropDecodeResizeOperation::from_json);
  274. ops_ptr[vision::kRandomCropOperation] = &(vision::RandomCropOperation::from_json);
  275. ops_ptr[vision::kRandomCropWithBBoxOperation] = &(vision::RandomCropWithBBoxOperation::from_json);
  276. ops_ptr[vision::kRandomHorizontalFlipOperation] = &(vision::RandomHorizontalFlipOperation::from_json);
  277. ops_ptr[vision::kRandomHorizontalFlipWithBBoxOperation] = &(vision::RandomHorizontalFlipWithBBoxOperation::from_json);
  278. ops_ptr[vision::kRandomPosterizeOperation] = &(vision::RandomPosterizeOperation::from_json);
  279. ops_ptr[vision::kRandomResizeOperation] = &(vision::RandomResizeOperation::from_json);
  280. ops_ptr[vision::kRandomResizeWithBBoxOperation] = &(vision::RandomResizeWithBBoxOperation::from_json);
  281. ops_ptr[vision::kRandomResizedCropOperation] = &(vision::RandomResizedCropOperation::from_json);
  282. ops_ptr[vision::kRandomResizedCropWithBBoxOperation] = &(vision::RandomResizedCropWithBBoxOperation::from_json);
  283. ops_ptr[vision::kRandomRotationOperation] = &(vision::RandomRotationOperation::from_json);
  284. ops_ptr[vision::kRandomSelectSubpolicyOperation] = &(vision::RandomSelectSubpolicyOperation::from_json);
  285. ops_ptr[vision::kRandomSharpnessOperation] = &(vision::RandomSharpnessOperation::from_json);
  286. ops_ptr[vision::kRandomSolarizeOperation] = &(vision::RandomSolarizeOperation::from_json);
  287. ops_ptr[vision::kRandomVerticalFlipOperation] = &(vision::RandomVerticalFlipOperation::from_json);
  288. ops_ptr[vision::kRandomVerticalFlipWithBBoxOperation] = &(vision::RandomVerticalFlipWithBBoxOperation::from_json);
  289. ops_ptr[vision::kRandomSharpnessOperation] = &(vision::RandomSharpnessOperation::from_json);
  290. ops_ptr[vision::kRandomSolarizeOperation] = &(vision::RandomSolarizeOperation::from_json);
  291. ops_ptr[vision::kRescaleOperation] = &(vision::RescaleOperation::from_json);
  292. ops_ptr[vision::kResizeOperation] = &(vision::ResizeOperation::from_json);
  293. ops_ptr[vision::kResizePreserveAROperation] = &(vision::ResizePreserveAROperation::from_json);
  294. ops_ptr[vision::kResizeWithBBoxOperation] = &(vision::ResizeWithBBoxOperation::from_json);
  295. ops_ptr[vision::kRgbaToBgrOperation] = &(vision::RgbaToBgrOperation::from_json);
  296. ops_ptr[vision::kRgbaToRgbOperation] = &(vision::RgbaToRgbOperation::from_json);
  297. ops_ptr[vision::kRgbToBgrOperation] = &(vision::RgbToBgrOperation::from_json);
  298. ops_ptr[vision::kRgbToGrayOperation] = &(vision::RgbToGrayOperation::from_json);
  299. ops_ptr[vision::kRotateOperation] = &(vision::RotateOperation::from_json);
  300. ops_ptr[vision::kSlicePatchesOperation] = &(vision::SlicePatchesOperation::from_json);
  301. ops_ptr[vision::kSoftDvppDecodeRandomCropResizeJpegOperation] =
  302. &(vision::SoftDvppDecodeRandomCropResizeJpegOperation::from_json);
  303. ops_ptr[vision::kSoftDvppDecodeResizeJpegOperation] = &(vision::SoftDvppDecodeResizeJpegOperation::from_json);
  304. ops_ptr[vision::kSwapRedBlueOperation] = &(vision::SwapRedBlueOperation::from_json);
  305. ops_ptr[vision::kUniformAugOperation] = &(vision::UniformAugOperation::from_json);
  306. ops_ptr[vision::kVerticalFlipOperation] = &(vision::VerticalFlipOperation::from_json);
  307. ops_ptr[transforms::kFillOperation] = &(transforms::FillOperation::from_json);
  308. ops_ptr[transforms::kOneHotOperation] = &(transforms::OneHotOperation::from_json);
  309. ops_ptr[transforms::kTypeCastOperation] = &(transforms::TypeCastOperation::from_json);
  310. ops_ptr[text::kToNumberOperation] = &(text::ToNumberOperation::from_json);
  311. return ops_ptr;
  312. }
  313. Status Serdes::ParseMindIRPreprocess(const std::string &dataset_json, const std::string &process_column,
  314. std::vector<std::shared_ptr<mindspore::dataset::Execute>> *data_graph) {
  315. CHECK_FAIL_RETURN_UNEXPECTED(!dataset_json.empty(), "Invalid data, no json data in dataset_json.");
  316. nlohmann::json dataset_js;
  317. try {
  318. dataset_js = nlohmann::json::parse(dataset_json);
  319. } catch (const std::exception &err) {
  320. MS_LOG(ERROR) << "Invalid json content, failed to parse JSON data, error message: " << err.what();
  321. RETURN_STATUS_UNEXPECTED("Invalid json content, failed to parse JSON data.");
  322. }
  323. // Note1: We have to consider if pipeline has multibranch, how to deal with this situation?
  324. // op1 - map - |
  325. // op2 - map - concat - map - ...
  326. std::stack<nlohmann::json> reverse_traversal;
  327. nlohmann::json dataset_nodes = dataset_js;
  328. while (dataset_nodes != nullptr) {
  329. reverse_traversal.push(dataset_nodes);
  330. if (dataset_nodes["children"].size() > 1) {
  331. MS_LOG(WARNING) << "Need to support dataset_node with more than one child.";
  332. }
  333. dataset_nodes = dataset_nodes["children"][0];
  334. }
  335. // Note2: We have to consider if the "image" column does not named with "image", how to select its map ops?
  336. // In MindRecord, TFRecord, GeneratorDataset or RenameDataset, it seems that the column names are not fixed.
  337. while (!reverse_traversal.empty()) {
  338. nlohmann::json node = reverse_traversal.top();
  339. reverse_traversal.pop();
  340. if (node["op_type"] == "Map") {
  341. std::vector<std::shared_ptr<TensorOperation>> tensor_ops;
  342. RETURN_IF_NOT_OK(ConstructTensorOps(node["operations"], &tensor_ops));
  343. if (node["input_columns"][0] == process_column) {
  344. std::vector<std::string> op_names;
  345. std::transform(tensor_ops.begin(), tensor_ops.end(), std::back_inserter(op_names),
  346. [](const auto &op) { return op->Name(); });
  347. MS_LOG(INFO) << "Find valid preprocess operations: " << op_names;
  348. data_graph->push_back(std::make_shared<Execute>(tensor_ops));
  349. }
  350. }
  351. }
  352. if (!data_graph->size()) {
  353. MS_LOG(WARNING) << "Can not find any valid preprocess operation.";
  354. }
  355. return Status::OK();
  356. }
  357. // In the current stage, there is a cyclic dependency between libmindspore.so and c_dataengine.so,
  358. // we make a C function here and dlopen by libminspore.so to avoid linking explicitly,
  359. // will be fix after decouling libminspore.so into multi submodules
  360. extern "C" {
  361. // ParseMindIRPreprocess_C has C-linkage specified, but returns user-defined type 'mindspore::Status'
  362. // which is incompatible with C
  363. void ParseMindIRPreprocess_C(const std::string &dataset_json, const std::string &process_column,
  364. std::vector<std::shared_ptr<mindspore::dataset::Execute>> *data_graph, Status *s) {
  365. Status ret = Serdes::ParseMindIRPreprocess(dataset_json, process_column, data_graph);
  366. *s = Status(ret);
  367. }
  368. }
  369. } // namespace dataset
  370. } // namespace mindspore