/**
Simulated data of proton-proton collisions of the TPC,
one set of tracks is given,
with single measured events of electron clouds reaching one of the two read-out chambers after a certain time with a certain charge

KV, 02/2010 (Data from Matevz Tadel), prepared for SBEII
**/

(
				// single setup script - read all data as prep.
q = ();
q.dataFolder = Document.current.dir ++ "/TPC_m_data_96/";
q.myfileName = "m_data_96";

// get all tracks including [tracknumber, # of data associated with track]:
q.headerArchive = ZArchive.read(q.dataFolder +/+ q.myfileName ++ "_tracks.zar");
q.trackInfos = q.headerArchive.readItem;

	// read and post data for ONE track:
q.readTPC = { |q, index = 0|
	var trackID = q.trackInfos[index][0];
	var trackArchive = ZArchive.read(q.dataFolder +/+ q.myfileName ++ "_" ++ trackID ++ ".zar");
	var data = trackArchive.readItem;
	trackArchive.close; 
	
		// correct time! 
	data.do { |track, i| 
		track[3] = (track[4].abs)/2.6 * 100 
	}; 
 	data
};
	// q.readTPC(14);

q.allTracks = q.trackInfos.size.collect { |i| 
	var track = q.readTPC(i);
	"read track %.\n".postf(i);
	track
};
)

/**
( 'trackInfos': 
	// id, numPoints
[ [ 5, 32961 ], 
	[ 8, 1810 ], 
	[ 33, 2364 ], 
	[ 34, 2261 ], 
	[ 35, 2531 ], 
	[ 36, 23 ], 
	[ 39, 5467 ], 
	[ 44, 7137 ], 
	[ 50, 8793 ], 
	[ 51, 2916 ], 
	[ 57, 28699 ], 
	[ 59, 6145 ], 
	[ 67, 15309 ], 
	[ 68, 9 ], 
	[ 70, 15503 ] ]
	
	// [units are in cm]
	q.track = q.allTracks[0];
	i = q.track[0] 	// track id, 			
	r = q.track[1]		// radius 	r,		[0..250] cm 
	p = q.track.flop[2] 	// angle 		phi,		[-pi, pi]
	t = q.track.flop[3]	// time 		t,		[0, 100] microsec, 
											= (2.6-(z.abs))/2.58 (2.58=drift velocity)
											BUT sometimes negative, therefore corrected!
	z = q.track.flop[4] 	// coordinate	z,		[-2.6, 2.6] // in meter: total size is 5m!
	x = q.track.flop[5] 	// coordinate	x,		[-250, 250] cm		
	y = q.track.flop[6] 	// coordinate	y, 		[-200, 225] cm
	c = q.track.flop[7] 	// charge 	q,  		in out.dat: [0, 272] nb. of electrons
	k = q.track.flop[8]		// kind of particle that produced the track, see TPCmontecarlorpp.pdf
	
	q.track.flop.do { |x| x.plot }; // plot all.
	q.track.flop.plot2; // plot all.
**/

	// look at one track
q.track = q.allTracks[0];

	// wie kann der radius von 250 auf 84 zurueckspringen? 
	// zwei unabhaengige bahnen zusammengesetzt? 
q.track.collect(_[1]).plot2; 
	// seltsamer sprung im detail hier: 
q.track.collect(_[1]).copyRange(3900, 4100).plot
	// warum ist t bei track0 zickzack????? 
q.track.collect(_[3]).plot2;

/*
	// ein guter beispiel track! 
q.track = q.allTracks[1];
q.track.collect(_[1]).plot2 // glatt bis aufs ende
q.track.collect(_[2]).plot2 // glatt bis aufs ende
*/

	// alle daten normalisieren und in buffers lesen  
(
q.radBufs = q.allTracks.collect { |track| 
	Buffer.loadCollection(s, track.collect(_[1])  / 250) 
};

q.angleBufs = q.allTracks.collect { |track| 
		Buffer.loadCollection(s, track.collect(_[2]).linlin(-pi, pi, -1, 1)) 
	};
)
/*
	// tests fuer buffers
q.radBufs[0].plot;
q.radBufs[1].plot;
q.angleBufs[1].plot;
q.radBufs.collect(_.bufnum);
q.angleBufs.collect(_.bufnum);

q.radBufs.collect(_.bufnum);

*/

	// einen track spielen: radbuf ist die buffer number.
	// mapping: 
			radius steuert tohoehe, aussen ist tief
			angle steuert formfreq und panposition
			spruenge in der glattheit der beiden datensignale 
			loesen laute amplitude aus, wenn glatt dezent leise.
(
Spec.add(\playrate, [0.001, 1, \exp]);
Spec.add(\radbuf, [q.radBufs.collect(_.bufnum).minItem, q.radBufs.collect(_.bufnum).maxItem, \lin, 1]);
Spec.add(\anglebuf, [q.angleBufs.collect(_.bufnum).minItem, q.angleBufs.collect(_.bufnum).maxItem, \lin, 1]);

Ndef(\form).edit;

Ndef(\form).awake = false;
Ndef(\form, { |radbuf = 1, anglebuf = 16, playrate = 0.05|
	var rad = PlayBuf.ar(1, radbuf, playrate, doneAction: 2);
	var angleRead = PlayBuf.ar(1, anglebuf, playrate, doneAction: 2);
	var formfreq = (angleRead * pi).sin.linexp(-1, 1, 1000, 6000);
	var panpos = angleRead;
	
	var glaette = HPZ1.ar([rad,angleRead] * Line.ar(-1, 1, 0.0001).max(0)).abs;
	var gain = LagUD.ar(glaette.linexp(0, 0.2, 0.01, 1), 0, 0.1);
	PanAz.ar(2, 
		Formant.ar(rad.linexp(1, 0, 50, 500), formfreq, formfreq * 0.2)
		* gain
	) ;
}).play;

q.playTrack = { |q, trackNum = 1, playrate = 0.01| 
	Ndef(\form).play;
	Ndef(\form).spawn([
		\radbuf, q.radBufs[trackNum].bufnum, 
		\anglebuf, q.angleBufs[trackNum].bufnum, 
		\playrate, playrate]
	)
};
)

	// which track, what speed
q.playTrack(1, 0.025)
q.playTrack(1, 0.1)
q.playTrack(5, 0.01)
q.playTrack(5, 0.001)
q.playTrack(0, 0.125)

	// play all in sequence
(
Tdef(\tpc, { 
	Ndef(\form).play;
	q.radBufs.do { |buf, i|
		q.playTrack(i.postln, 0.025);
		(buf.duration * 20).postln.wait;
	}
}).play
)

	// play single tracks or all tracks from gui
(
w = Window("Play TPC Trax", Rect(300, 300, 400, 200)).front;
w.addFlowLayout;
15.do { |i|
		Button(w, Rect(0,0, 75, 40)).states_([[i.asString]])
		.action_({ q.playTrack(i) });
	};
Button(w, Rect(0,0, 390, 40)).states_([["ALL"]])
	.action_({ q.radBufs.do { |rad, i| q.playTrack(i) } });
)