j@253
|
1 (cl:in-package #:amuse-charm)
|
j@253
|
2
|
j@253
|
3 (defun make-charm-property-list (&rest properties)
|
j@253
|
4 (make-instance 'charm-property-list
|
j@253
|
5 :%data properties))
|
j@253
|
6
|
j@253
|
7 (defun make-charm-constituent-identifier (id)
|
j@253
|
8 (make-instance 'charm-constituent-identifier
|
j@253
|
9 :constituent-id id))
|
j@253
|
10
|
j@253
|
11 (defun make-standard-charm-constituent (particles parent
|
j@253
|
12 extrinsic-properties
|
j@253
|
13 intrinsic-properties &key
|
j@253
|
14 start duration
|
j@253
|
15 constituent-identifier owner
|
j@253
|
16 version creation-timestamp
|
j@253
|
17 deletion-timestamp)
|
j@253
|
18 "Properties should be charm-property-lists. FIXME: enforce this?
|
j@253
|
19 What about time? Should we be using implementation time data-types?
|
j@253
|
20 Particles by definition are identifiers - BUT this seemed to cause
|
j@253
|
21 unnecessary pain, so particales are now either events or
|
j@253
|
22 constituents. This could be made to call a backend specific
|
j@253
|
23 constructor specialised on the parent-identifier."
|
j@253
|
24 (make-instance 'standard-charm-constituent
|
j@253
|
25 :identifier constituent-identifier
|
j@253
|
26 :parent parent
|
j@253
|
27 :time start ; FIXME: naming conventions?
|
j@253
|
28 :interval duration
|
j@253
|
29 :extrinsic-properties extrinsic-properties
|
j@253
|
30 :intrinsic-properties intrinsic-properties
|
j@253
|
31 :%data particles
|
j@253
|
32 :owner owner
|
j@253
|
33 :version version
|
j@253
|
34 :creation-timestamp creation-timestamp
|
j@253
|
35 :deletion-timestamp deletion-timestamp))
|
j@253
|
36
|
j@253
|
37 (defun make-standard-charm-event-constituent (particles parent
|
j@253
|
38 extrinsic-properties
|
j@253
|
39 intrinsic-properties
|
j@253
|
40 &key start duration
|
j@253
|
41 constituent-identifier
|
j@253
|
42 owner version
|
j@253
|
43 creation-timestamp
|
j@253
|
44 deletion-timestamp)
|
j@253
|
45 (make-instance 'standard-charm-event-constituent
|
j@253
|
46 :identifier constituent-identifier
|
j@253
|
47 :parent parent
|
j@253
|
48 :time start ; FIXME: naming conventions?
|
j@253
|
49 :interval duration
|
j@253
|
50 :extrinsic-properties extrinsic-properties
|
j@253
|
51 :intrinsic-properties intrinsic-properties
|
j@253
|
52 :%data particles
|
j@253
|
53 :owner owner
|
j@253
|
54 :version version
|
j@253
|
55 :creation-timestamp creation-timestamp
|
j@253
|
56 :deletion-timestamp deletion-timestamp))
|
j@253
|
57
|
j@253
|
58 (defun composition->charm-constituent (composition
|
j@253
|
59 extrinsic-properties
|
j@253
|
60 intrinsic-properties)
|
j@253
|
61 "This is currently the bridge that takes us from AMuSE compositions
|
j@253
|
62 to Charm constituents."
|
j@253
|
63 (make-standard-charm-event-constituent (%list-slot-sequence-data
|
j@253
|
64 composition) composition
|
j@253
|
65 extrinsic-properties
|
j@253
|
66 intrinsic-properties
|
j@253
|
67 :start (timepoint
|
j@253
|
68 composition)
|
j@253
|
69 :duration (duration
|
j@253
|
70 composition)))
|
j@253
|
71
|
j@253
|
72 (defun make-onset-segment-constituent (composition)
|
j@253
|
73 "So this makes a constituent for each set of events with the same
|
j@253
|
74 onset, and adds all of those as particles to a parent constituent. To
|
j@253
|
75 two levels are created, maybe it's better to only return a list of
|
j@253
|
76 onset-constituents, and the user can group them together within
|
j@253
|
77 another constituent if necessary?"
|
j@253
|
78 (let ((grouped-events (group-by-onset composition))
|
j@253
|
79 (parent-constituent
|
j@253
|
80 (make-standard-charm-constituent nil composition
|
j@253
|
81 (make-charm-property-list
|
j@253
|
82 'sequence-class)
|
j@253
|
83 (make-charm-property-list
|
j@253
|
84 'sequence-class)
|
j@253
|
85 :start (timepoint
|
j@253
|
86 composition)
|
j@253
|
87 :duration (duration
|
j@253
|
88 composition))))
|
j@253
|
89 (loop for beat-events in grouped-events
|
j@253
|
90 collect (make-standard-charm-event-constituent
|
j@253
|
91 beat-events
|
j@253
|
92 parent-constituent
|
j@253
|
93 (make-charm-property-list 'segment)
|
j@253
|
94 (make-charm-property-list 'onset-segment))
|
j@253
|
95 into constituents
|
j@253
|
96 finally (progn
|
j@253
|
97 (setf (%list-slot-sequence-data parent-constituent)
|
j@253
|
98 constituents)
|
j@253
|
99 (return parent-constituent)))))
|
j@253
|
100
|
j@253
|
101 (defun group-by-onset (composition)
|
j@253
|
102 (loop for event in (reverse (%list-slot-sequence-data composition))
|
j@253
|
103 with grouped-events
|
j@253
|
104 do (if (and grouped-events
|
j@253
|
105 (time= (onset event) (onset (car (car grouped-events)))))
|
j@253
|
106 (push event (car grouped-events))
|
j@253
|
107 (push (list event) grouped-events))
|
j@253
|
108 finally (return grouped-events)))
|
j@253
|
109
|
j@253
|
110 (defun segment-at-bar (composition)
|
j@253
|
111 "Returns a list of bar-constituents."
|
j@253
|
112 (loop with current-bar = (current-bar (elt composition 0) composition) and current-events
|
j@253
|
113 for event in (%list-slot-sequence-data composition)
|
j@253
|
114 if (time= current-bar (current-bar event composition))
|
j@253
|
115 do (push event current-events)
|
j@253
|
116 else
|
j@253
|
117 collect (make-standard-charm-event-constituent
|
j@253
|
118 (reverse current-events)
|
j@253
|
119 composition
|
j@253
|
120 (make-charm-property-list)
|
j@253
|
121 (make-charm-property-list 'segment 'bar))
|
j@253
|
122 into constituents
|
j@253
|
123 and do (setf current-bar (current-bar event composition))
|
j@253
|
124 and do (setf current-events nil)
|
j@253
|
125 finally (return constituents)))
|