/////////////// TPC Group 2 ///////////
// Programmer: Till Bovermann
///////// Read Data
// 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
(
q = ();
q.datFiles = [1, 6, 10, 30, 96];
q.allAllTPCData = q.datFiles.collect{|ext|
var allTPCdata;
q.dataFolder = Document.current.dir ++ "/TPC_m_data_%/".format(ext);
q.myfileName = "m_data_%".format(ext);
// 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;
data.do { |track, i|
track[3] = (track[4].abs)/2.6 * 100
}; // correct time!
data
};
// q.readTPC(14);
allTPCdata = q.trackInfos.size.collect { |i|
var track = q.readTPC(i);
"read track %.\n".postf(i);
track
};
};
)
q.allTPCdata = q.allAllTPCData[0]
// tests
q.allTPCdata.shape;
q.allTPCdata[1].shape;
(
// get physical values at minimum of radius
q.getPhysical = {|q, trackId = 0, eventID = 0|
var minR, minIdxR, minPhi, charge, secParTheta, z, type;
// get smallest value in q.rIdx
minR = q.allAllTPCData[eventID][trackId].flop[1].minItem;
minIdxR = q.allAllTPCData[eventID][trackId].flop[1].minIndex;
// phi at minimum of radius
minPhi = q.allAllTPCData[eventID][trackId].flop[2][minIdxR];
// deposited track charge (q)
charge = q.allAllTPCData[eventID][trackId].flop[7].sum;
// secondary Particle Theta
// multiply by 100 to keep scaling (m -> cm)
z = q.allAllTPCData[eventID][trackId].flop[4][minIdxR] * 100;
secParTheta = atan(z, minR);
type = q.allAllTPCData[eventID][trackId].flop[8][minIdxR];
[minR, minPhi, charge, secParTheta, type]
};
)
/* test
q.getPhysical(0, 0); // */
(
// get all physical data needed for sonification
q.physicalDatas = q.allAllTPCData.collect{|event, eventID|
event.size.collect{|i|
[i, eventID].postln;
q.getPhysical(i, eventID);
}
};
/* tests
q.physicalDatas[1].flop.plot2;
q.allTPCdata[5].flop[1].minIndex;
q.allTPCdata[5].flop[1][12] // */
)
// A parametermapping of the five computed attributes, tracks played in a row
(
SynthDef(\physicalMapping, {|out = 0, freq = 100, pan = 0, dur = 1, amp = 1, brilliance = 3000|
var src, env, panner;
src = LPF.ar(LFSaw.ar(freq), brilliance);
env = EnvGen.ar(Env.perc(0.01, dur-0.01), doneAction: 2);
panner = Pan2.ar(src * env, pan, amp);
Out.ar(out, panner);
}).memStore;
Tdef(\player, {
var minR,minPhi, charge, secParTheta, type, time, lastTime = 0, dt;
var freq, amp, dur, pan, brilliance;
1.do{
q.sortedData.do{|row|
# minR, minPhi, charge, secParTheta, type = row;
// mapping...
freq = type.abs + 100;
amp = charge.linlin(0, 100000, 1, 5).reciprocal;
pan = type.sign;
dur = secParTheta.linlin(-0.5pi, 0.5pi, 0.1, 0.5);
time = minPhi.linlin(-pi, pi, 0, 3);
brilliance = secParTheta.linexp(-0.5pi, 0.5pi, 500, 10000);
[freq, amp, dur, pan, brilliance, time-lastTime].postln;
(time - lastTime).wait;
(instrument: \physicalMapping, freq: freq, amp: amp, pan: pan, dur: dur).play;
lastTime = time;
};
1.wait;
}
});
// trigger events
q.triggerIt = {|q, eventID = 0|
q.sortedData = q.physicalDatas[eventID].deepCopy.sort{|a, b|
a[1] < b[1]
};
Tdef(\player).play;
}
)
// do!
q.triggerIt(0);
q.triggerIt(1);
q.triggerIt(2);
q.triggerIt(3);
q.triggerIt(4);