comparison Sources/DicomScpCallbacks.cpp @ 151:566df919b286 cmove2

new more detailed C-Move SCP callbacks
author Alain Mazy <am@osimis.io>
date Tue, 27 Feb 2024 16:13:08 +0100
parents c55b0583084b
children a6b4e0abe532
comparison
equal deleted inserted replaced
150:3c98306828de 151:566df919b286
28 28
29 static PyObject* findScpCallback_ = NULL; 29 static PyObject* findScpCallback_ = NULL;
30 static PyObject* moveScpCallback_ = NULL; 30 static PyObject* moveScpCallback_ = NULL;
31 static PyObject* worklistScpCallback_ = NULL; 31 static PyObject* worklistScpCallback_ = NULL;
32 32
33 // version 2 of Move callbacks
34 static PyObject* createMoveScpDriverCallback_ = NULL;
35 static PyObject* getMoveSizeCallback_ = NULL;
36 static PyObject* applyMoveCallback_ = NULL;
37 static PyObject* freeMoveCallback_ = NULL;
38
33 39
34 static PyObject *GetFindQueryTag(sdk_OrthancPluginFindQuery_Object* self, 40 static PyObject *GetFindQueryTag(sdk_OrthancPluginFindQuery_Object* self,
35 PyObject *args, 41 PyObject *args,
36 bool isGroup) 42 bool isGroup)
37 { 43 {
397 assert(moveDriver != NULL); 403 assert(moveDriver != NULL);
398 delete reinterpret_cast<IMoveDriver*>(moveDriver); 404 delete reinterpret_cast<IMoveDriver*>(moveDriver);
399 } 405 }
400 406
401 407
408 static void* CreateMoveCallback2(OrthancPluginResourceType resourceType,
409 const char *patientId,
410 const char *accessionNumber,
411 const char *studyInstanceUid,
412 const char *seriesInstanceUid,
413 const char *sopInstanceUid,
414 const char *originatorAet,
415 const char *sourceAet,
416 const char *targetAet,
417 uint16_t originatorId)
418 {
419 assert(createMoveScpDriverCallback_ != NULL);
420
421 try
422 {
423 std::string _patientId, _accessionNumber, _studyInstanceUid, _seriesInstanceUid, _sopInstanceUid, _originatorAet, _sourceAet, _targetAet;
424 if (patientId != NULL)
425 {
426 _patientId.assign(patientId);
427 }
428
429 if (accessionNumber != NULL)
430 {
431 _accessionNumber.assign(accessionNumber);
432 }
433
434 if (studyInstanceUid != NULL)
435 {
436 _studyInstanceUid.assign(studyInstanceUid);
437 }
438
439 if (seriesInstanceUid != NULL)
440 {
441 _seriesInstanceUid.assign(seriesInstanceUid);
442 }
443
444 if (sopInstanceUid != NULL)
445 {
446 _sopInstanceUid.assign(sopInstanceUid);
447 }
448
449 if (originatorAet != NULL)
450 {
451 _originatorAet.assign(originatorAet);
452 }
453
454 if (sourceAet != NULL)
455 {
456 _sourceAet.assign(sourceAet);
457 }
458
459 if (targetAet != NULL)
460 {
461 _targetAet.assign(targetAet);
462 }
463
464 PythonLock lock;
465
466 PythonObject kw(lock, PyDict_New());
467
468 std::string level;
469 switch (resourceType)
470 {
471 case OrthancPluginResourceType_Patient:
472 level = "PATIENT";
473 break;
474
475 case OrthancPluginResourceType_Study:
476 level = "STUDY";
477 break;
478
479 case OrthancPluginResourceType_Series:
480 level = "SERIES";
481 break;
482
483 case OrthancPluginResourceType_Instance:
484 level = "INSTANCE";
485 break;
486
487 default:
488 throw OrthancPlugins::PluginException(OrthancPluginErrorCode_ParameterOutOfRange);
489 }
490
491 {
492 PythonString tmp(lock, level);
493 PyDict_SetItemString(kw.GetPyObject(), "Level", tmp.GetPyObject());
494 }
495
496 {
497 PythonString tmp(lock, _patientId);
498 PyDict_SetItemString(kw.GetPyObject(), "PatientID", tmp.GetPyObject());
499 }
500
501 {
502 PythonString tmp(lock, _accessionNumber);
503 PyDict_SetItemString(kw.GetPyObject(), "AccessionNumber", tmp.GetPyObject());
504 }
505
506 {
507 PythonString tmp(lock, _studyInstanceUid);
508 PyDict_SetItemString(kw.GetPyObject(), "StudyInstanceUID", tmp.GetPyObject());
509 }
510
511 {
512 PythonString tmp(lock, _seriesInstanceUid);
513 PyDict_SetItemString(kw.GetPyObject(), "SeriesInstanceUID", tmp.GetPyObject());
514 }
515
516 {
517 PythonString tmp(lock, _sopInstanceUid);
518 PyDict_SetItemString(kw.GetPyObject(), "SOPInstanceUID", tmp.GetPyObject());
519 }
520
521 {
522 PythonString tmp(lock, _originatorAet);
523 PyDict_SetItemString(kw.GetPyObject(), "OriginatorAET", tmp.GetPyObject());
524 }
525
526 {
527 PythonString tmp(lock, _sourceAet);
528 PyDict_SetItemString(kw.GetPyObject(), "SourceAET", tmp.GetPyObject());
529 }
530
531 {
532 PythonString tmp(lock, _targetAet);
533 PyDict_SetItemString(kw.GetPyObject(), "TargetAET", tmp.GetPyObject());
534 }
535
536 {
537 PythonObject tmp(lock, PyLong_FromUnsignedLong(originatorId));
538 PyDict_SetItemString(kw.GetPyObject(), "OriginatorID", tmp.GetPyObject());
539 }
540
541 PythonObject args(lock, PyTuple_New(0));
542
543 // Note: the result is not attached to the PythonLock because we want it to survive after this call since
544 // the result is the python move driver that will be passed as first argument to GetMoveSize, Apply and Free
545 std::unique_ptr<PyObject> result(PyObject_Call(createMoveScpDriverCallback_, args.GetPyObject(), kw.GetPyObject()));
546
547 OrthancPluginErrorCode code = lock.CheckCallbackSuccess("Python C-MOVE SCP callback (Create)");
548 if (code != OrthancPluginErrorCode_Success)
549 {
550 throw OrthancPlugins::PluginException(code);
551 }
552
553 // make sure it survives after this call
554 Py_INCREF(result.get());
555
556 return result.release();
557 }
558 catch (OrthancPlugins::PluginException& e)
559 {
560 return NULL;
561 }
562 }
563
564
565 static uint32_t GetMoveSize2(void *moveDriver)
566 {
567 assert(moveDriver != NULL);
568 assert(getMoveSizeCallback_ != NULL);
569
570 PythonLock lock;
571
572 PythonObject args(lock, PyTuple_New(1));
573 PyTuple_SetItem(args.GetPyObject(), 0, reinterpret_cast<PyObject*>(moveDriver));
574 Py_INCREF(moveDriver); // because PyTuple_SetItem steals a reference and we need to keep the object alive
575
576 PythonObject result(lock, PyObject_CallObject(getMoveSizeCallback_, args.GetPyObject()));
577
578 OrthancPluginErrorCode code = lock.CheckCallbackSuccess("Python C-MOVE SCP callback (GetMoveSize)");
579 if (code != OrthancPluginErrorCode_Success)
580 {
581 throw OrthancPlugins::PluginException(code);
582 }
583
584 if (!PyLong_Check(result.GetPyObject()))
585 {
586 throw OrthancPlugins::PluginException(OrthancPluginErrorCode_BadParameterType);
587 }
588
589 return static_cast<uint32_t>(PyLong_AsLong(result.GetPyObject()));
590 }
591
592
593 OrthancPluginErrorCode ApplyMove2(void *moveDriver)
594 {
595 assert(moveDriver != NULL);
596 assert(applyMoveCallback_ != NULL);
597
598 PythonLock lock;
599
600 PythonObject args(lock, PyTuple_New(1));
601 PyTuple_SetItem(args.GetPyObject(), 0, reinterpret_cast<PyObject*>(moveDriver));
602 Py_INCREF(moveDriver); // because PyTuple_SetItem steals a reference and we need to keep the object alive
603
604 PythonObject result(lock, PyObject_CallObject(applyMoveCallback_, args.GetPyObject()));
605
606 OrthancPluginErrorCode code = lock.CheckCallbackSuccess("Python C-MOVE SCP callback (Apply)");
607 return code;
608 }
609
610
611 void FreeMove2(void *moveDriver)
612 {
613 assert(moveDriver != NULL);
614
615 PythonLock lock;
616
617 PythonObject args(lock, PyTuple_New(1));
618 PyTuple_SetItem(args.GetPyObject(), 0, reinterpret_cast<PyObject*>(moveDriver));
619 Py_INCREF(moveDriver); // because PyTuple_SetItem steals a reference and we need to keep the object alive
620
621 assert(freeMoveCallback_ != NULL);
622 PythonObject result(lock, PyObject_CallObject(freeMoveCallback_, args.GetPyObject()));
623
624 lock.CheckCallbackSuccess("Python C-MOVE SCP callback (Free)");
625
626 Py_DECREF(moveDriver);
627 }
628
402 629
403 OrthancPluginErrorCode WorklistCallback(OrthancPluginWorklistAnswers *answers, 630 OrthancPluginErrorCode WorklistCallback(OrthancPluginWorklistAnswers *answers,
404 const OrthancPluginWorklistQuery *query, 631 const OrthancPluginWorklistQuery *query,
405 const char *issuerAet, 632 const char *issuerAet,
406 const char *calledAet) 633 const char *calledAet)
485 return ICallbackRegistration::Apply( 712 return ICallbackRegistration::Apply(
486 registration, args, moveScpCallback_, "Python C-MOVE SCP callback"); 713 registration, args, moveScpCallback_, "Python C-MOVE SCP callback");
487 } 714 }
488 715
489 716
717 PyObject* RegisterMoveCallback2(PyObject* module, PyObject* args)
718 {
719 // The GIL is locked at this point (no need to create "PythonLock")
720
721 class Registration : public ICallbackRegistration
722 {
723 public:
724 virtual void Register() ORTHANC_OVERRIDE
725 {
726 OrthancPluginRegisterMoveCallback(
727 OrthancPlugins::GetGlobalContext(), CreateMoveCallback2, GetMoveSize2, ApplyMove2, FreeMove2);
728 }
729 };
730
731 Registration registration;
732 return ICallbackRegistration::Apply4(
733 registration, args, createMoveScpDriverCallback_, getMoveSizeCallback_, applyMoveCallback_, freeMoveCallback_, "Python C-MOVE SCP callback (2)");
734 }
735
490 PyObject* RegisterWorklistCallback(PyObject* module, PyObject* args) 736 PyObject* RegisterWorklistCallback(PyObject* module, PyObject* args)
491 { 737 {
492 // The GIL is locked at this point (no need to create "PythonLock") 738 // The GIL is locked at this point (no need to create "PythonLock")
493 739
494 class Registration : public ICallbackRegistration 740 class Registration : public ICallbackRegistration
509 void FinalizeDicomScpCallbacks() 755 void FinalizeDicomScpCallbacks()
510 { 756 {
511 ICallbackRegistration::Unregister(findScpCallback_); 757 ICallbackRegistration::Unregister(findScpCallback_);
512 ICallbackRegistration::Unregister(moveScpCallback_); 758 ICallbackRegistration::Unregister(moveScpCallback_);
513 ICallbackRegistration::Unregister(worklistScpCallback_); 759 ICallbackRegistration::Unregister(worklistScpCallback_);
514 } 760
761 ICallbackRegistration::Unregister(createMoveScpDriverCallback_);
762 ICallbackRegistration::Unregister(getMoveSizeCallback_);
763 ICallbackRegistration::Unregister(applyMoveCallback_);
764 ICallbackRegistration::Unregister(freeMoveCallback_);
765 }