373RModel Parse(std::string filename, std::vector<std::vector<size_t>> inputShapes, std::vector<ETensorType> inputDTypes){
380 size_t isep = filename.rfind(sep, filename.length());
381 std::string filename_nodir = filename;
382 if (isep != std::string::npos){
383 filename_nodir = (filename.substr(isep+1, filename.length() - isep));
387 if(!std::ifstream(filename).good()){
388 throw std::runtime_error(
"Model file "+filename_nodir+
" not found!");
392 std::time_t ttime = std::time(0);
393 std::tm* gmt_time = std::gmtime(&ttime);
394 std::string parsetime (std::asctime(gmt_time));
396 RModel rmodel(filename_nodir, parsetime);
404 throw std::runtime_error(
"Can't init global namespace for Python");
407 throw std::runtime_error(
"Can't init local namespace for Python");
414 PyRunString(
"import torch",fGlobalNS,fLocalNS);
415 PyRunString(
"print('Torch Version: '+torch.__version__)",fGlobalNS,fLocalNS);
416 PyRunString(
"from torch.onnx.utils import _model_to_graph",fGlobalNS,fLocalNS);
418 PyRunString(
TString::Format(
"model= torch.jit.load('%s')",filename.c_str()),fGlobalNS,fLocalNS);
419 PyRunString(
"globals().update(locals())",fGlobalNS,fLocalNS);
420 PyRunString(
"model.cpu()",fGlobalNS,fLocalNS);
421 PyRunString(
"model.eval()",fGlobalNS,fLocalNS);
424 PyRunString(
"dummyInputs=[]",fGlobalNS,fLocalNS);
425 for(
long unsigned int it=0;it<inputShapes.size();++it){
426 PyRunString(
"inputShape=[]",fGlobalNS,fLocalNS);
427 for(
long unsigned int itr=0;itr<inputShapes[it].size();++itr){
428 PyRunString(
TString::Format(
"inputShape.append(%d)",(
int)inputShapes[it][itr]),fGlobalNS,fLocalNS);
430 PyRunString(
"dummyInputs.append(torch.rand(*inputShape))",fGlobalNS,fLocalNS);
436 PyRunString(
"graph=_model_to_graph(model,dummyInputs)",fGlobalNS,fLocalNS);
440 PyRunString(
"modelData=[]",fGlobalNS,fLocalNS);
443 PyRunString(
"def _node_get(node, key):\n"
444 " sel = node.kindOf(key)\n"
445 " return getattr(node, sel)(key)\n",
446 fGlobalNS, fLocalNS);
447 PyRunString(
"for i in graph[0].nodes():\n"
448 " globals().update(locals())\n"
450 " nodeData['nodeType']=i.kind()\n"
451 " nodeAttributeNames=[x for x in i.attributeNames()]\n"
452 " nodeAttributes={j: _node_get(i, j) for j in nodeAttributeNames}\n"
453 " nodeData['nodeAttributes']=nodeAttributes\n"
454 " nodeInputs=[x for x in i.inputs()]\n"
455 " nodeInputNames=[x.debugName() for x in nodeInputs]\n"
456 " nodeData['nodeInputs']=nodeInputNames\n"
457 " nodeOutputs=[x for x in i.outputs()]\n"
458 " nodeOutputNames=[x.debugName() for x in nodeOutputs]\n"
459 " nodeData['nodeOutputs']=nodeOutputNames\n"
460 " nodeDType=[x.type().scalarType() for x in nodeOutputs]\n"
461 " nodeData['nodeDType']=nodeDType\n"
462 " modelData.append(nodeData)",
463 fGlobalNS, fLocalNS);
465 PyObject* fPModel = PyDict_GetItemString(fLocalNS,
"modelData");
466 Py_ssize_t fPModelSize = PyList_Size(fPModel);
468 std::string fNodeType;
471 for(
Py_ssize_t fModelIterator=0;fModelIterator<fPModelSize;++fModelIterator){
472 fNode = PyList_GetItem(fPModel,fModelIterator);
473 fNodeType = PyStringAsString(PyDict_GetItemString(fNode,
"nodeType"));
476 if(fNodeType ==
"onnx::Gemm"){
479 else if(fNodeType ==
"onnx::Selu" || fNodeType ==
"onnx::Sigmoid"){
482 else if (fNodeType ==
"onnx::Conv") {
490 PyRunString(
"weightNames=[k for k in graph[1].keys()]",fGlobalNS,fLocalNS);
491 PyRunString(
"weights=[v.numpy() for v in graph[1].values()]",fGlobalNS,fLocalNS);
492 PyRunString(
"weightDTypes=[v.type()[6:-6] for v in graph[1].values()]",fGlobalNS,fLocalNS);
493 PyObject* fPWeightNames = PyDict_GetItemString(fLocalNS,
"weightNames");
494 PyObject* fPWeightTensors = PyDict_GetItemString(fLocalNS,
"weights");
495 PyObject* fPWeightDTypes = PyDict_GetItemString(fLocalNS,
"weightDTypes");
496 PyArrayObject* fWeightTensor;
497 std::string fWeightName;
499 std::vector<std::size_t> fWeightShape;
500 std::size_t fWeightSize;
502 for(
Py_ssize_t weightIter=0; weightIter<PyList_Size(fPWeightTensors);++weightIter){
503 fWeightTensor = (PyArrayObject*)PyList_GetItem(fPWeightTensors,weightIter);
504 fWeightName = PyStringAsString(PyList_GetItem(fPWeightNames,weightIter));
505 fWeightDType =
ConvertStringToType(PyStringAsString(PyList_GetItem(fPWeightDTypes,weightIter)));
507 fWeightShape.clear();
508 for(
int j=0; j<PyArray_NDIM(fWeightTensor); ++j){
509 fWeightShape.push_back((std::size_t)(PyArray_DIM(fWeightTensor,j)));
510 fWeightSize*=(std::size_t)(PyArray_DIM(fWeightTensor,j));
512 switch(fWeightDType){
514 float* fWeightValue = (
float*)PyArray_DATA(fWeightTensor);
515 std::shared_ptr<void> fData(
malloc(fWeightSize *
sizeof(
float)),
free);
516 std::memcpy(fData.get(),fWeightValue,fWeightSize *
sizeof(
float));
521 throw std::runtime_error(
"Type error: TMVA SOFIE does not yet supports weights of data type"+
ConvertTypeToString(fWeightDType));
527 PyRunString(
"inputs=[x for x in model.graph.inputs()]",fGlobalNS,fLocalNS);
528 PyRunString(
"inputs=inputs[1:]",fGlobalNS,fLocalNS);
529 PyRunString(
"inputNames=[x.debugName() for x in inputs]",fGlobalNS,fLocalNS);
530 PyObject* fPInputs= PyDict_GetItemString(fLocalNS,
"inputNames");
531 std::string fInputName;
532 std::vector<size_t>fInputShape;
534 for(
Py_ssize_t inputIter=0; inputIter<PyList_Size(fPInputs);++inputIter){
535 fInputName = PyStringAsString(PyList_GetItem(fPInputs,inputIter));
536 fInputShape = inputShapes[inputIter];
537 fInputDType = inputDTypes[inputIter];
545 throw std::runtime_error(
"Type Error: TMVA SOFIE does not yet support the input tensor data type"+
ConvertTypeToString(fInputDType));
551 PyRunString(
"outputs=[x for x in graph[0].outputs()]",fGlobalNS,fLocalNS);
552 PyRunString(
"outputNames=[x.debugName() for x in outputs]",fGlobalNS,fLocalNS);
553 PyObject* fPOutputs= PyDict_GetItemString(fLocalNS,
"outputNames");
554 std::vector<std::string> fOutputNames;
555 for(
Py_ssize_t outputIter = 0; outputIter < PyList_Size(fPOutputs);++outputIter){
556 fOutputNames.push_back(PyStringAsString(PyList_GetItem(fPOutputs,outputIter)));