-
Notifications
You must be signed in to change notification settings - Fork 0
/
StimInfo.m
257 lines (228 loc) · 9.43 KB
/
StimInfo.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
//
// StimInfo.m
// FeatureViewer
//
// Created by Roger Herikstad on 13/11/11.
// Copyright 2011 NUS. All rights reserved.
//
#import "StimInfo.h"
@implementation StimInfo
@synthesize descriptor;
@synthesize framepts,repBoundaries;
@synthesize nframes,framesPerRep,nreps;
@synthesize sessionName,sessionPath;
@synthesize repDuration;
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
-(void)readFromFile:(NSString*)fname
{
//check that file exists
if( [[NSFileManager defaultManager] fileExistsAtPath: fname] )
{
sessionPath = [[fname stringByDeletingLastPathComponent] retain];
sessionName = [[[fname lastPathComponent] stringByDeletingPathExtension] retain];
data = [[NSMutableDictionary dictionary] retain];
//get lines
NSArray *lines = [[NSString stringWithContentsOfFile: fname] componentsSeparatedByString: @"\n"];
//lines = [lines filterArr
NSEnumerator *linesEnumerator = [lines objectEnumerator];
NSString *line = [linesEnumerator nextObject];
NSMutableDictionary *currentDict = [NSMutableDictionary dictionary];
while( line )
{
if( [line isEqualToString: @""] ==NO)
{
NSArray *keysAndObjects = [line componentsSeparatedByString: @"="];
if([keysAndObjects count] > 1 )
{
[currentDict setObject: [[keysAndObjects objectAtIndex:1] lowercaseString] forKey: [[keysAndObjects objectAtIndex:0] lowercaseString]];
}
else if ([keysAndObjects count] ==1 )
{
NSString *keyName = [[keysAndObjects objectAtIndex:0] lowercaseString];
NSRange _r1 = [keyName rangeOfString: @"["];
NSRange _r2 = [keyName rangeOfString: @"]"];
keyName = [[keyName substringWithRange: NSMakeRange(_r1.location+1,_r2.location-_r1.location-1)] capitalizedString];
[data setObject: [NSMutableDictionary dictionary] forKey: keyName];
currentDict = [data objectForKey: keyName];
}
}
line = [linesEnumerator nextObject];
}
}
}
-(void)readMonitorSyncs
{
NSString *fname = [sessionPath stringByAppendingPathComponent: [sessionName stringByAppendingPathExtension: @"snc"]];
if( [[NSFileManager defaultManager] fileExistsAtPath: fname] )
{
//read data
NSData *_data = [NSData dataWithContentsOfFile: fname];
unsigned int offset = 0;
//read the header
unsigned int headersize, records;
double meanF,stdF;
char dname[260];
[_data getBytes: &headersize range: NSMakeRange(offset,4)];
offset+=4;
[_data getBytes: dname range: NSMakeRange(offset,260)];
offset+=260;
[_data getBytes: &records range: NSMakeRange(offset,4)];
offset+=4;
[_data getBytes: &meanF range: NSMakeRange(offset,8)];
offset+=8;
[_data getBytes: &stdF range: NSMakeRange(offset,8)];
offset+=8;
syncs = [[_data subdataWithRange: NSMakeRange(headersize,[_data length]-headersize)] retain];
}
}
-(void)readDescriptor
{
NSString *contents = [NSString stringWithContentsOfFile: [sessionPath stringByAppendingPathComponent: [sessionName stringByAppendingString: @"_descriptor.txt"]]];
NSArray *lines = [contents componentsSeparatedByString: @"\n"];
NSEnumerator *linesEnumerator = [lines objectEnumerator];
//Skip the first line
NSString *line = [linesEnumerator nextObject];
line = [linesEnumerator nextObject];
NSUInteger channels = [[[line componentsSeparatedByString:@" "] lastObject] intValue];
line = [linesEnumerator nextObject];
double sampling_rate = [[[line componentsSeparatedByString:@" "] lastObject] doubleValue];
//skip one line
line = [linesEnumerator nextObject];
line = [linesEnumerator nextObject];
double gain = [[[line componentsSeparatedByString:@" "] lastObject] doubleValue];
//skip one line
line = [linesEnumerator nextObject];
line = [linesEnumerator nextObject];
//iterate throgh lines
NSMutableArray *chNr = [NSMutableArray arrayWithCapacity: 100];
NSMutableArray *grNr = [NSMutableArray arrayWithCapacity: 100];
NSMutableArray *status = [NSMutableArray arrayWithCapacity:100];
NSMutableArray *type = [NSMutableArray arrayWithCapacity:100];
int ch, gr;
NSString *_type,*_status;
while( line )
{
NSScanner *scanner = [NSScanner scannerWithString:line];
//get the channel number
[scanner scanInt:&ch];
//get the type
[scanner scanUpToCharactersFromSet:[NSCharacterSet whitespaceCharacterSet] intoString:&_type];
//get the group number
[scanner scanInt:&gr];
//get the status
[scanner scanUpToCharactersFromSet:[NSCharacterSet whitespaceCharacterSet] intoString:&_status];
//NSArray *parts = [line componentsSeparatedByString:@ " "];
//int nparts = [parts count];
[chNr addObject: [NSNumber numberWithInt:ch]];
[grNr addObject: [NSNumber numberWithInt: gr]];
[type addObject: _type];
[status addObject: [NSNumber numberWithBool: [_status isEqualToString: @"Active"]]];
line = [linesEnumerator nextObject];
}
[self setDescriptor: [NSDictionary dictionaryWithObjectsAndKeys: chNr, @"channelNumber", grNr, @"groupNumber",status,@"status",type,@"type",[NSNumber numberWithInt:channels],@"numChannels", [NSNumber numberWithFloat:sampling_rate], @"samplingRate",[NSNumber numberWithFloat: gain],@"gain",nil]];
}
-(void)getFramePoints
{
if([self descriptor] == NULL)
{
[self readDescriptor];
}
if( syncs == NULL )
{
[self readMonitorSyncs];
}
//compute the frame points by finding the number of syncs per frame
int syncs_per_frame = [[[data objectForKey:@"Treversecorrguiform"] objectForKey:@"refreshes per frame"] intValue];
double sr = [[[self descriptor] objectForKey:@"samplingRate"] doubleValue];
uint32_t *_syncs = (uint32_t*)[syncs bytes];
unsigned int _nsyncs = [syncs length]/sizeof(uint32_t);
unsigned int _nframes = floor(_nsyncs/syncs_per_frame);
double *_framepts = malloc(floor(_nsyncs/syncs_per_frame)*sizeof(double));
unsigned int i,j;
j = 0;
for(i=0;i<_nsyncs;i+=syncs_per_frame)
{
//we want framepts in ms
_framepts[j] = (double)_syncs[i]/sr*1000.0;
j+=1;
}
//check the type of stimulus
if([[[data objectForKey: @"Treversecorrguiform"] objectForKey:@"object type"] hasPrefix:@"grating"] )
{
[self setNreps: [[[data objectForKey: @"Treversecorrguiform"] objectForKey:@"number of blocks"] intValue]] ;
}
else
{
[self setNreps: [[[data objectForKey: @"Treversecorrguiform"] objectForKey:@"number Of repeats"] intValue]] ;
}
int _nreps = [self nreps];
int _framesPerRep = _nframes/_nreps;
double *_repBoundaries = malloc(_nreps*sizeof(double));
double _repDuration = 0;
double offset = 0;
//get the repetition boundaries and compute the (average) rep duration
for(i=0;i<_nreps;i++)
{
_repBoundaries[i] = _framepts[i*_framesPerRep];
_repDuration += _repBoundaries[i]-offset;
offset =_repBoundaries[i];
}
[self setRepDuration:[NSNumber numberWithDouble:_repDuration/_nreps]];
[self setFramesPerRep:_framesPerRep];
[self setFramepts:[NSData dataWithBytes:_framepts length:_nframes*sizeof(double)]];
[self setNframes:_nframes];
[self setRepBoundaries:[NSData dataWithBytes:_repBoundaries length:_nreps*sizeof(double)]];
//since the bytes have been copied, we can free the original location
free(_framepts);
free(_repBoundaries);
}
-(void)getTriggerSignalWithThreshold:(float)threshold
{
//make sure we have the descriptor first
if( descriptor == NULL )
{
[self readDescriptor];
}
//memory map the file
NSData *_data = [NSData dataWithContentsOfMappedFile: [sessionPath stringByAppendingPathComponent: [sessionName stringByAppendingPathExtension: @"bin"]]];
int triggerChannel = [[[self descriptor] objectForKey: @"type"] indexOfObject: @"presenter"];
int numChannels = [[[self descriptor] objectForKey:@"numChannels"] intValue];
//to get the data for the trigger channel
int headersize;
//get the header size
[_data getBytes: &headersize range: NSMakeRange(0,4)];
//get the number of bytes per channel
unsigned int pointsPerCh = ((unsigned int)[_data length]-headersize)/2/numChannels;
unsigned int *triggerPoints = malloc(pointsPerCh*sizeof(unsigned int));
unsigned int ntriggers = 0;
int i,j,previ;
j = 0;
previ =0;
int16_t buf;
//since we are doing this in a loop anyway, we can just detected the crossings directly
for(i=0;i<pointsPerCh;i++)
{
//for each datapoint we want to read, we have to
[_data getBytes: &buf range:NSMakeRange(headersize+2*(i*numChannels + triggerChannel),2)];
//only detect if it is the first crossing
if( (float)buf >= threshold )
{
if(i-previ > 1 )
{
//we have a crossing
triggerPoints[j] = i;
j+=1;
}
previ = i;
}
}
ntriggers = j;
}
@end