I need to modify storescp for the needs of research teams. We are a brain imaging center having research teams as customers for our MR-scanner from Siemens. In a clinical site, operators belong to the clinics and the images are transferred to PACS. In our case, the operator belong to the research teams and we would like to make the transfer of data faster than through usb on the MR-scanner computer and safer by creating users and view and edit rights. So linux is the easy way to go.
I have done some heavy modifications on storescp this time by adding a "--sort-on-study-description" option. I have actually tried to add rather to modify.
I don't pretend this configuration would be universal and suit all research centers, but I have adapted the script to brain research and Siemens MRI scanners.
I am not a programmer so I expect to have done mistakes in my programing but I have tried to be as much inspired as possible by the sturcture you have made on the option --sort-on-patientname.
- One of the goals is that researchers only have access to data belonging to their research group. A research group is identified by a "Principal Investigator" a.k.a. "PI". The highest level of storage directories is then the PI's diectory.
Code: Select all
OFString pidirectoryPathAndName;
- A principal investigator can run different project. So a project will define the second level of directories:
Code: Select all
OFString projectdirectoryPathAndName;
- Each project is constituted of many exams for which a participant, volonteer or patient is scanned.
Code: Select all
OFString examdirectoryPathAndName;
- And I am using the variable "subdirectoryName" for each sequence that has been run or reconstructed in each exam.
Code: Select all
OFString subdirectoryName;
- Siemens software on the MR-scanner (Syngo) sends the following for the dicom tag studyDescription: "UnknownRegion^UnknownExam^UnknownProgram". For clinical scans it makes sense as they work with Regions (i.e. brain, neck, heart, etc), Exams (type of examination) and Programs (list of sequences). But for the research mode, it does not make sense. So I have substituted "Region" with "Principal Investigator" and "Exam" with "Project" in order to get "PrincipalInvestigator'sName^ProjectName^ProtocolName" returned in studyDdescription. As Syngo sends "^" as a separator, I have slightly modified the latin table.
(please note that "Exam" in research language means a particular examination on a specific participant on a certain time schedule while "Exam" in Siemens language seems to refer to the type of examination run on a "Region".).
Code: Select all
"P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "_", "_", "_", "^", "_", // Codes 80-95
- I have added a big portion of code begining around line 1834 with
where I create a few strings that will be used in the directory names and file names: currentStudyDescription, currentPatientName, examDate and examTime.
Code: Select all
if (opt_sortStudyMode == ESM_StudyDescription)
- I then cut the strings into substrings that I use for naming the directories (around line 1970).
The examination's directory is specific to an exam, a participant, a date and a time in the day (sometimes the same participant is scanned at the beggining of the day and at the end of the day within the same project)
Code: Select all
pidirectoryName = currentStudyDescription.substr(0, pos); // the first substring of the studyDescirption tag is the PI's name projectdirectoryName = currentStudyDescription.substr(0, pos); // the second substring (if it exists) is delimited by "^" and refers to the project's name protocolName = currentStudyDescription; // the third substring (if it exists) is delimited by "^" and refers to theprotocol's name
Code: Select all
//"[Patient's Name]_[YYYYMMDD]_[HHMMSS]" if ((pos = currentPatientName.find(delimiter)) != OFString_npos) examdirectoryName = currentPatientName.substr(0, pos); // the patient name in research is never the actual patient's name but an id in the study. For instance, subject 201 may have id aub201 or pat201 or whatever is decided. else examdirectoryName = currentPatientName; examdirectoryName += '_'; examdirectoryName += examDate; examdirectoryName += '_'; examdirectoryName += examTime;
- Later I create the directories corresponding to the different MR-sequences that have been run on the participant:
Code: Select all
if ((*imageDataSet)->findAndGetOFString(DCM_SeriesDescription, subdirectoryName).bad() || subdirectoryName.empty()) //creates the subdirectory name based first on the SeriesDescription ... subdirectoryName +="_"; ... subdirectoryName += seriesNumber; //add the series number in a 3 digits format in the string.
- Finally I create the file's name in an 8-digits format with .dcm as extension.
The code compiles, and I debugg it from time to time.
Code: Select all
size_t in1length=tmpfileName.length(); size_t inlength=7-in1length; shortfileName ="0"; for (size_t i = 0; i < inlength; i++) shortfileName +="0"; shortfileName = shortfileName + tmpfileName + ".dcm"; } OFStandard::combineDirAndFilename(fileName, subdirectoryPathAndName, shortfileName); // update global variable outputFileNameArray // (might be used in executeOnReception() and renameOnEndOfStudy) outputFileNameArray.push_back(shortfileName);
I could join a .diff file as attachment containing the whole patch.
Since the code is largely extended and that I am not a programmer, would you recommend sending the code to more advanced programmers for verification or would you advise to adopt another strategy?
Thank you,
Best,
Jonathan