Skip to content

Commit

Permalink
BrowserController: comparatives studies, work in progress
Browse files Browse the repository at this point in the history
git-svn-id: https://svn.code.sf.net/p/osirix/code/osirix@10057 4e9e6e3d-4551-47eb-9dbe-a6127f9400a1
  • Loading branch information
rossetantoine committed Jul 4, 2012
1 parent 7bc2da9 commit d460a35
Show file tree
Hide file tree
Showing 8 changed files with 2,193 additions and 1,797 deletions.
3,768 changes: 2,022 additions & 1,746 deletions Binaries/English.lproj/MainMenu.xib

Large diffs are not rendered by default.

12 changes: 0 additions & 12 deletions DCMTKQueryNode.h
Expand Up @@ -16,18 +16,6 @@
#import <Cocoa/Cocoa.h>
#import "DCMTKServiceClassUser.h"

#undef verify

#include "osconfig.h" /* make sure OS specific configuration is included first */
#include "dcdatset.h"
#include "dimse.h"
#include "dccodec.h"
//#include "tlstrans.h"
//#include "tlslayer.h"
//#include "ofstring.h"



@class DCMCalendarDate;
/** \brief Base class for query nodes */
@interface DCMTKQueryNode : DCMTKServiceClassUser
Expand Down
2 changes: 2 additions & 0 deletions DCMTKQueryNode.mm
Expand Up @@ -35,6 +35,8 @@
#include <libkern/OSAtomic.h>

#undef verify
#include "dccodec.h"

#include "osconfig.h" /* make sure OS specific configuration is included first */

#include "dctag.h"
Expand Down
16 changes: 12 additions & 4 deletions DCMTKServiceClassUser.h
Expand Up @@ -20,16 +20,24 @@ Super Class for SCU classes such as verifySCU, storeSCU, moveSCU, findSCU

#import <Cocoa/Cocoa.h>

#ifdef __cplusplus
#undef verify

#include "osconfig.h" /* make sure OS specific configuration is included first */
#include "dcdatset.h"
#include "dimse.h"
#include "dccodec.h"
//#include "tlstrans.h"
//#include "tlslayer.h"
//#include "ofstring.h"

#else

typedef int E_TransferSyntax;
typedef int T_DIMSE_BlockingMode;
typedef char* OFCondition;
typedef char* T_ASC_Parameters;
typedef char* DcmDataset;
typedef char* T_ASC_Association;
typedef char* T_ASC_Network;

#endif

/** \brief Base Class for SCU classes such as verifySCU, storeSCU, moveSCU, findSCU
*
Expand Down
2 changes: 2 additions & 0 deletions DCMTKStudyQueryNode.h
Expand Up @@ -20,4 +20,6 @@

}

- (NSString*) studyInstanceUID;
- (NSString*) studyName;
@end
14 changes: 14 additions & 0 deletions DCMTKStudyQueryNode.mm
Expand Up @@ -199,6 +199,20 @@ - (DcmDataset *)moveDataset
return dataset;
}

- (DCMCalendarDate*) date // Match DicomStudy
{
return [DCMCalendarDate dicomDateTimeWithDicomDate: _date dicomTime: _time];
}

- (NSString*) studyInstanceUID // Match DicomStudy
{
return _uid;
}

- (NSString*) studyName // Match DicomStudy
{
return _theDescription;
}

- (void)addChild:(DcmDataset *)dataset
{
Expand Down
5 changes: 4 additions & 1 deletion browserController.h
Expand Up @@ -223,6 +223,9 @@ extern NSString* O2AlbumDragType;
NSTimeInterval _timeIntervalOfLastLoadIconsDisplayIcons;

BOOL subSeriesWindowIsOn;

NSString *comparativePatientUID;
NSArray *comparativeStudies;
}

@property(retain,nonatomic) DicomDatabase* database;
Expand All @@ -240,7 +243,7 @@ extern NSString* O2AlbumDragType;
@property(readonly) BonjourBrowser *bonjourBrowser;
@property(readonly) const char *cfixedDocumentsDirectory __deprecated, *cfixedIncomingDirectory __deprecated, *cfixedTempNoIndexDirectory __deprecated, *cfixedIncomingNoIndexDirectory __deprecated;

@property(retain) NSString *searchString, *CDpassword, *pathToEncryptedFile, *passwordForExportEncryption, *temporaryNotificationEmail, *customTextNotificationEmail;
@property(retain) NSString *searchString, *CDpassword, *pathToEncryptedFile, *passwordForExportEncryption, *temporaryNotificationEmail, *customTextNotificationEmail, *comparativePatientUID;
@property(retain) NSPredicate *fetchPredicate, *testPredicate;
@property(readonly) NSPredicate *filterPredicate;
@property(readonly) NSString *filterPredicateDescription;
Expand Down
171 changes: 137 additions & 34 deletions browserController.m
Expand Up @@ -17,6 +17,7 @@
#import "DicomDatabase.h"
#import "DicomDatabase+Routing.h"
#import "DicomDatabase+DCMTK.h"
#import "DCMTKStudyQueryNode.h"
#import "DicomDatabase+Scan.h"
#import "RemoteDicomDatabase.h"
#import "SRAnnotation.h"
Expand Down Expand Up @@ -280,15 +281,13 @@ +(void)initialize
// [decimalNumberFormatter setHasThousandSeparators: YES];
}

@class DCMTKStudyQueryNode;

@synthesize database = _database;
@synthesize sources = _sourcesArrayController;

@synthesize CDpassword, passwordForExportEncryption, databaseIndexDictionary;
@synthesize TimeFormat, TimeWithSecondsFormat, temporaryNotificationEmail, customTextNotificationEmail;
@synthesize DateTimeWithSecondsFormat, matrixViewArray, oMatrix, testPredicate;
@synthesize databaseOutline, albumTable;
@synthesize databaseOutline, albumTable, comparativePatientUID;
@synthesize bonjourSourcesBox, timeIntervalType;
@synthesize bonjourBrowser, pathToEncryptedFile;
@synthesize searchString = _searchString, fetchPredicate = _fetchPredicate;
Expand Down Expand Up @@ -3472,34 +3471,123 @@ - (NSMutableArray *)filesForDatabaseOutlineSelection :(NSMutableArray*) correspo

- (void) resetROIsAndKeysButton
{
ROIsAndKeyImagesButtonAvailable = YES;
ROIsAndKeyImagesButtonAvailable = NO;

// NSMutableArray *i = [NSMutableArray arrayWithArray: [[toolbar items] valueForKey: @"itemIdentifier"]];
// if( [i containsString: OpenKeyImagesAndROIsToolbarItemIdentifier] && [database isLocal])
// {
// if( [[databaseOutline selectedRowIndexes] count] >= 5) //[[self window] firstResponder] == databaseOutline &&
// ROIsAndKeyImagesButtonAvailable = YES;
// else
// {
// NSEvent *event = [[NSApplication sharedApplication] currentEvent];
//
// if([event modifierFlags] & NSAlternateKeyMask)
// {
// if( [[self KeyImages: nil] count] == 0) ROIsAndKeyImagesButtonAvailable = NO;
// else ROIsAndKeyImagesButtonAvailable = YES;
// }
// else if([event modifierFlags] & NSShiftKeyMask)
// {
// if( [[self ROIImages: nil] count] == 0) ROIsAndKeyImagesButtonAvailable = NO;
// else ROIsAndKeyImagesButtonAvailable = YES;
// }
// else
// {
// if( [[self ROIsAndKeyImages: nil] count] == 0) ROIsAndKeyImagesButtonAvailable = NO;
// else ROIsAndKeyImagesButtonAvailable = YES;
// }
// }
// }
NSMutableArray *i = [NSMutableArray arrayWithArray: [[toolbar items] valueForKey: @"itemIdentifier"]];
if( [i containsString: OpenKeyImagesAndROIsToolbarItemIdentifier] && [_database isLocal])
{
if( [[databaseOutline selectedRowIndexes] count] >= 5) //[[self window] firstResponder] == databaseOutline &&
ROIsAndKeyImagesButtonAvailable = YES;
else
{
NSEvent *event = [[NSApplication sharedApplication] currentEvent];

if([event modifierFlags] & NSAlternateKeyMask)
{
if( [[self KeyImages: nil] count] == 0) ROIsAndKeyImagesButtonAvailable = NO;
else ROIsAndKeyImagesButtonAvailable = YES;
}
else if([event modifierFlags] & NSShiftKeyMask)
{
if( [[self ROIImages: nil] count] == 0) ROIsAndKeyImagesButtonAvailable = NO;
else ROIsAndKeyImagesButtonAvailable = YES;
}
else
{
if( [[self ROIsAndKeyImages: nil] count] == 0) ROIsAndKeyImagesButtonAvailable = NO;
else ROIsAndKeyImagesButtonAvailable = YES;
}
}
}
}

- (void) searchForComparativeStudies: (DicomStudy*) studySelected
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];

static NSRecursiveLock *searchForComparativeStudiesLock = nil;

if( !searchForComparativeStudiesLock)
searchForComparativeStudiesLock = [NSRecursiveLock new];

[searchForComparativeStudiesLock lock];
if( [self.comparativePatientUID isEqualToString: studySelected.patientUID]) // There was maybe other locks in the queue...
{
NSLog( @"--- Search for comparative studies: %@", studySelected.patientUID);

@try
{
BOOL usePatientID = [[NSUserDefaults standardUserDefaults] boolForKey: @"usePatientIDForComparativeSearch"];
BOOL usePatientName = [[NSUserDefaults standardUserDefaults] boolForKey: @"usePatientNameForComparativeSearch"];

// Servers
NSMutableArray* servers = [NSMutableArray array];
NSArray* sources = [DCMNetServiceDelegate DICOMServersList];
for (NSDictionary* si in sources)
{
if( [[[NSUserDefaults standardUserDefaults] arrayForKey: @"comparativeSearchDICOMNodes"] containsObject: [si objectForKey:@"Description"]])
{
[servers addObject: si];
}
}

// Distant studies
NSArray *distantStudies = nil;
#ifndef OSIRIX_LIGHT
distantStudies = [QueryController queryStudiesForPatient: studySelected usePatientID: usePatientID usePatientName: usePatientName servers: servers showErrors: YES];
#endif

// Local studies
NSArray *localStudies = nil;
@try
{
NSPredicate* predicate = [NSPredicate predicateWithFormat: @"(patientUID == %@)", studySelected.patientUID];
localStudies = [_database objectsForEntity:_database.studyEntity predicate:predicate];
}
@catch (NSException* e)
{
NSLog( @"*** Comparative Studies exception: %@", e);
}

// Merge local and distant studies
NSMutableArray *mergedStudies = [NSMutableArray arrayWithArray: localStudies];
#ifndef OSIRIX_LIGHT
for( DCMTKStudyQueryNode *distantStudy in distantStudies)
{
if( [[mergedStudies valueForKey: @"studyInstanceUID"] containsObject: [distantStudy studyInstanceUID]] == NO)
{
[mergedStudies addObject: distantStudy];
}
}
#endif

[mergedStudies sortUsingDescriptors: [NSArray arrayWithObject: [NSSortDescriptor sortDescriptorWithKey:@"date" ascending: NO]]];

for( id study in mergedStudies)
{
BOOL distant = NO;

#ifndef OSIRIX_LIGHT
distant = [study isKindOfClass: [DCMTKStudyQueryNode class]];

DCMTKStudyQueryNode *qrStudy = study;
DicomStudy *xcStudy = study;

[xcStudy name]; [xcStudy modality]; [xcStudy date]; [xcStudy studyName]; //For warnings report
[qrStudy name]; [qrStudy modality]; [qrStudy date], [qrStudy studyName]; //For warnings report
#endif

NSLog( @"%d Patient name: %@ - %@ - %@ - %@", distant, [study name], [study modality], [[NSUserDefaults dateTimeFormatter] stringFromDate: [study date]], [study studyName]);
}
}
@catch (NSException* e)
{
N2LogExceptionWithStackTrace(e);
}
}
[searchForComparativeStudiesLock unlock];

[pool release];
}

- (void)outlineViewSelectionDidChange: (NSNotification *)aNotification
Expand Down Expand Up @@ -3534,7 +3622,7 @@ - (void)outlineViewSelectionDidChange: (NSNotification *)aNotification
/**********
post notification of new selected item. Can be used by plugins to update RIS connection
**********/
NSManagedObject *studySelected = [[item valueForKey: @"type"] isEqualToString: @"Study"] ? item : [item valueForKey: @"study"];
DicomStudy *studySelected = [[item valueForKey: @"type"] isEqualToString: @"Study"] ? item : [item valueForKey: @"study"];

NSDictionary *userInfo = nil;
if( studySelected)
Expand Down Expand Up @@ -3603,6 +3691,23 @@ - (void)outlineViewSelectionDidChange: (NSNotification *)aNotification
{
[previousItem release];
previousItem = [item retain];

// COMPARATIVE STUDIES

// [[NSUserDefaults standardUserDefaults] setBool: YES forKey: @"searchForComparativeStudiesOnDICOMNodes"];
// [[NSUserDefaults standardUserDefaults] setBool: YES forKey: @"usePatientIDForComparativeSearch"];
// [[NSUserDefaults standardUserDefaults] setBool: YES forKey: @"usePatientNameForComparativeSearch"];
// [[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObject: @"MINIPACS"] forKey: @"comparativeSearchDICOMNodes"];

if( [[NSUserDefaults standardUserDefaults] boolForKey: @"searchForComparativeStudiesOnDICOMNodes"])
{
if( [studySelected.patientUID isEqualToString: self.comparativePatientUID] == NO)
{
self.comparativePatientUID = studySelected.patientUID;

[NSThread detachNewThreadSelector: @selector( searchForComparativeStudies:) toTarget:self withObject:studySelected];
}
}
}

[self resetROIsAndKeysButton];
Expand All @@ -3619,8 +3724,6 @@ - (void)outlineViewSelectionDidChange: (NSNotification *)aNotification
}

[self splitView:splitViewVert resizeSubviewsWithOldSize:[splitViewVert bounds].size];


}
@catch (NSException * e)
{
Expand Down Expand Up @@ -16675,7 +16778,7 @@ - (BOOL)validateToolbarItem: (NSToolbarItem *)toolbarItem

if ([[toolbarItem itemIdentifier] isEqualToString: OpenKeyImagesAndROIsToolbarItemIdentifier])
{
return YES; //ROIsAndKeyImagesButtonAvailable;
return ROIsAndKeyImagesButtonAvailable;
}

if ([[toolbarItem itemIdentifier] isEqualToString: ViewersToolbarItemIdentifier])
Expand Down

0 comments on commit d460a35

Please sign in to comment.