major cleanup and development of tracker

main
mwinter 1 year ago
parent e1a2324b0c
commit 5ffb61d4f4

@ -1,171 +1,216 @@
// Include the AccelStepper library:
#include <AccelStepper.h>
// Define stepper motor connections and motor interface type. Motor interface type must be set to 1 when using a driver:
// Set stepper 1 pins
#define m1LimitNegPin 2
#define m1LimitPosPin 3
#define m1DirPin 4
#define m1StepPin 5
#define m1PowerPin 6
#define xLimitSwitchPosPin 2
#define xLimitSwitchNegPin 3
#define xDirPin 4
#define xStepPin 5
#define xPowerPin 6
// Set stepper 2 pins
#define m2LimitNegPin 9
#define m2LimitPosPin 10
#define m2DirPin 11
#define m2StepPin 12
#define m2PowerPin 13
#define yLimitSwitchPosPin 9
#define yLimitSwitchNegPin 10
#define yDirPin 11
#define yStepPin 12
#define yPowerPin 13
#define motorInterfaceType 1
// Create a new instance of the AccelStepper class:
AccelStepper m1Stepper = AccelStepper(motorInterfaceType, m1StepPin, m1DirPin);
AccelStepper m2Stepper = AccelStepper(motorInterfaceType, m2StepPin, m2DirPin);
// Create new instances of the AccelStepper class:
AccelStepper xStepper = AccelStepper(motorInterfaceType, xStepPin, xDirPin);
AccelStepper yStepper = AccelStepper(motorInterfaceType, yStepPin, yDirPin);
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
bool printMode = false;
void setup() {
// safeMode means that the limit has been hit
bool xSafeMode = false;
long xLimitPos = 0;
pinMode(m1PowerPin, OUTPUT);
pinMode(m1LimitNegPin, INPUT);
pinMode(m1LimitPosPin, INPUT);
bool ySafeMode = false;
long yLimitPos = 0;
pinMode(m2PowerPin, OUTPUT);
pinMode(m2LimitNegPin, INPUT);
pinMode(m2LimitPosPin, INPUT);
int microsteps = 1;
float maxSpeedConstant = 350 * microsteps;
float accelerationConstant = 100 * microsteps;
Serial.begin(115200);
void setup() {
// Set the maximum speed in steps per second:
m1Stepper.setMaxSpeed(200);
m1Stepper.setAcceleration(100);
m1Stepper.setCurrentPosition(0);
m2Stepper.setMaxSpeed(200);
m2Stepper.setAcceleration(100);
m2Stepper.setCurrentPosition(0);
}
pinMode(xPowerPin, OUTPUT);
pinMode(xLimitSwitchNegPin, INPUT);
pinMode(xLimitSwitchPosPin, INPUT);
pinMode(yPowerPin, OUTPUT);
pinMode(yLimitSwitchNegPin, INPUT);
pinMode(yLimitSwitchPosPin, INPUT);
int integerValue=0;
bool negativeNumber = false; // track if number is negative
char incomingByte;
void loop() {
currentMillis = millis();
int m1EorNeg = digitalRead(m1LimitNegPin);
int m1EorPos = digitalRead(m1LimitPosPin);
int m2EorNeg = digitalRead(m2LimitNegPin);
int m2EorPos = digitalRead(m2LimitPosPin);
if (currentMillis - previousMillis >= 1000 == true ) {
Serial.println("------Stepper 1------");
Serial.print("m1EorPos:");
Serial.println(m1EorNeg);
Serial.print("m1EorNeg: ");
Serial.println(m1EorPos);
Serial.print("m1CurPos: ");
Serial.println(m1Stepper.currentPosition() * -1);
Serial.print("m1TarPos: ");
Serial.println(m1Stepper.targetPosition() * -1);
Serial.println("");
Serial.begin(115200);
Serial.println("------Stepper 2------");
Serial.print("m2EorPos: ");
Serial.println(m2EorNeg);
Serial.print("m2EorNeg: ");
Serial.println(m2EorPos);
Serial.print("m2CurPos: ");
Serial.println(m2Stepper.currentPosition() * -1);
Serial.print("m2TarPos: ");
Serial.println(m2Stepper.targetPosition() * -1);
Serial.println("");
xStepper.setMaxSpeed(maxSpeedConstant);
xStepper.setAcceleration(accelerationConstant);
//xStepper.setCurrentPosition(0);
previousMillis = currentMillis;
}
yStepper.setMaxSpeed(maxSpeedConstant);
yStepper.setAcceleration(accelerationConstant);
//yStepper.setCurrentPosition(0);
}
// limit switch logic for stepper 1
if ((m1EorNeg < m1EorPos) && (m1Stepper.targetPosition() > m1Stepper.currentPosition())) {
m1Stepper.setSpeed(0);
m1Stepper.moveTo(m1Stepper.currentPosition());
digitalWrite(m1PowerPin, HIGH);
} else if ((m1EorNeg > m1EorPos) && (m1Stepper.targetPosition() < m1Stepper.currentPosition())) {
m1Stepper.setSpeed(0);
m1Stepper.moveTo(m1Stepper.currentPosition());
digitalWrite(m1PowerPin, HIGH);
} else if (m1Stepper.targetPosition() == m1Stepper.currentPosition()) {
digitalWrite(m1PowerPin, HIGH);
void stepperLogic(int stepperIndex, bool printMode){
// init vars
AccelStepper *stepper;
int powerPin;
int limitSwitchNeg;
int limitSwitchPos;
bool *safeMode;
long *limitPos;
// set vars based on stepper index
if(stepperIndex == 1){
stepper = &xStepper;
powerPin = xPowerPin;
limitSwitchNeg = digitalRead(xLimitSwitchNegPin);
limitSwitchPos = digitalRead(xLimitSwitchPosPin);
safeMode = &xSafeMode;
limitPos = &xLimitPos;
} else {
digitalWrite(m1PowerPin, LOW);
m1Stepper.run();
stepper = &yStepper;
powerPin = yPowerPin;
limitSwitchNeg = digitalRead(yLimitSwitchNegPin);
limitSwitchPos = digitalRead(yLimitSwitchPosPin);
safeMode = &ySafeMode;
limitPos = &yLimitPos;
}
// limit switch logic for stepper 2
if ((m2EorNeg < m2EorPos) && (m2Stepper.targetPosition() > m2Stepper.currentPosition())) {
m2Stepper.setSpeed(0);
m2Stepper.moveTo(m2Stepper.currentPosition());
digitalWrite(m2PowerPin, HIGH);
} else if ((m2EorNeg > m2EorPos) && (m2Stepper.targetPosition() < m2Stepper.currentPosition())) {
m2Stepper.setSpeed(0);
m2Stepper.moveTo(m1Stepper.currentPosition());
digitalWrite(m2PowerPin, HIGH);
} else if (m2Stepper.targetPosition() == m2Stepper.currentPosition()) {
digitalWrite(m2PowerPin, HIGH);
// stepper logic
if (!*safeMode && (limitSwitchNeg == limitSwitchPos)){
// just keep swimming
digitalWrite(powerPin, LOW);
stepper->run();
//runLogic(stepperIndex, stepperFlip, stepper, last, distance, dir);
} else if (!*safeMode && (limitSwitchNeg != limitSwitchPos)) {
// limit hit; go into safeMode; power down
*safeMode = true;
*limitPos = stepper->currentPosition();
stepper->setSpeed(0);
stepper->moveTo(stepper->currentPosition());
digitalWrite(powerPin, HIGH);
Serial.println("!! limit hit, move the other direction");
} else if (*safeMode && (abs(*limitPos - stepper->currentPosition()) < (1000 * microsteps))) {
// just keep swimming for a while (only in the other direction), hoping to get out of safeMode within 1000 steps
if((limitSwitchNeg == 0 && (stepper->currentPosition() > stepper->targetPosition())) ||
(limitSwitchPos == 0 && (stepper->currentPosition() < stepper->targetPosition()))) {
*safeMode = (limitSwitchNeg != limitSwitchPos);
digitalWrite(powerPin, LOW);
stepper->run();
}
} else if (stepper->distanceToGo() == 0) {
// destination reached; power down
digitalWrite(powerPin, HIGH);
} else {
digitalWrite(m2PowerPin, LOW);
m2Stepper.run();
}
if (Serial.available() > 0) { // something came across serial
integerValue = 0; // throw away previous integerValue
negativeNumber = false; // reset for negative
// houston we have a problem; safeMode is still on after 10 steps from limitPos
stepper->setSpeed(0);
stepper->moveTo(stepper->currentPosition());
digitalWrite(powerPin, HIGH);
Serial.println("!!! limit switch still on after 1000 steps, this should NEVER happen");
};
if (printMode) {
//Serial.println("[" + String(stepperIndex) + ", " + String(stepper->currentPosition()) + ", " + String(stepper->targetPosition()) + ", " +
//String(limitSwitchNeg) + ", " + String(limitSwitchPos) + ", " + String(*safeMode) + ", " + String(*limitPos) + "]");
Serial.println("[" + String(xStepper.currentPosition()) + ", " + String(yStepper.currentPosition()) + ", " +
String(limitSwitchNeg) + ", " + String(limitSwitchPos) + "]");
/*
if (stepperIndex == 1){
Serial.println("------Stepper 1------");
} else {
Serial.println("------Stepper 2------");
};
Serial.print("curPos: ");
Serial.println(stepper->currentPosition());
Serial.print("tarPos: ");
Serial.println(stepper->targetPosition());
Serial.print("limitSwitchNeg: ");
Serial.println(limitSwitchNeg);
Serial.print("limitSwitchPos: ");
Serial.println(limitSwitchPos);
Serial.print("safeMode: ");
Serial.println(*safeMode);
Serial.print("limitPos: ");
Serial.println(*limitPos);
Serial.print("speed: ");
Serial.println(stepper->speed());
Serial.println("");
*/
while(1) { // force into a loop until 'n' is received
incomingByte = Serial.read();
if (incomingByte == ' ') break; // exit the while(1), we're done receiving
if (incomingByte == -1) continue; // if no characters are in the buffer read() returns -1
if (incomingByte == '-') {
negativeNumber = true;
continue;
}
integerValue *= 10; // shift left 1 decimal place
integerValue = ((incomingByte - 48) + integerValue); // convert ASCII to integer, add, and shift left 1 decimal place
}
if (negativeNumber)
integerValue = -integerValue;
}
integerValue = -integerValue; // this makes up for the fact that things are backwards
m1Stepper.moveTo(integerValue);
}
integerValue = 0; // throw away previous integerValue
negativeNumber = false; // reset for negative
while(1) { // force into a loop until 'n' is received
incomingByte = Serial.read();
if (incomingByte == '\n') break; // exit the while(1), we're done receiving
if (incomingByte == -1) continue; // if no characters are in the buffer read() returns -1
if (incomingByte == '-') {
negativeNumber = true;
continue;
}
integerValue *= 10; // shift left 1 decimal place
integerValue = ((incomingByte - 48) + integerValue); // convert ASCII to integer, add, and shift left 1 decimal place
long parseDest(char delimiter){
long integerValue = 0; // throw away previous integerValue
bool negativeNumber = false; // reset for negative
char incomingByte;
while(1) { // force into a loop until delimiter is received
incomingByte = Serial.read();
/*
if (incomingByte == 'c') {
xStepper.setCurrentPosition(0);
yStepper.setCurrentPosition(0);
continue;
}
if (negativeNumber)
integerValue = -integerValue;
*/
if (incomingByte == delimiter) break; // exit the while(1), we're done receiving
if (incomingByte == -1) continue; // if no characters are in the buffer read() returns -1
if (incomingByte == '-') {
negativeNumber = true;
continue;
}
integerValue *= 10; // shift left 1 decimal place
integerValue = ((incomingByte - 48) + integerValue); // convert ASCII to integer, add, and shift left 1 decimal place
}
if (negativeNumber)
integerValue = -integerValue;
//integerValue = -integerValue; // this makes up for the fact that things are backwards
return integerValue;
}
integerValue = -integerValue; // this makes up for the fact that things are backwards
m2Stepper.moveTo(integerValue);
void loop() {
currentMillis = millis();
printMode = false;
if (currentMillis - previousMillis >= 100 == true ) {
printMode = true;
previousMillis = currentMillis;
}
stepperLogic(1, printMode);
stepperLogic(2, printMode);
if (Serial.available() > 0) { // something came across serial
xStepper.moveTo(parseDest(' '));
yStepper.moveTo(parseDest('\n'));
};
//delay(100);
}

@ -9,3 +9,4 @@
\bibcite{Grunbaum:1986:TP:19304}{4}
\bibcite{Kari:1996:SAS:245761.245817}{5}
\bibcite{DBLP:journals/corr/JeandelR15}{6}
\gdef \@abspage@last{240}

@ -124,7 +124,7 @@ Between the two photomasks, there are nine embedded images which can be seen at
\end{center}
\begin{description}[labelindent=0.5cm]
\item [unidimensional Verniers:] These are the most useful markings for image alignment. For each axis, there are a set of coarse Verniers (bordering the image) and a set of fine Verniers (further from the image) which move 5 times the speed of the coarse Veniers. Everytime an image is aligned the white blob will be centered in both the coarse and fine Verniers. These markings essentially amplify and scale the distance between the image (640 microns) and can be used by a motion tracker in a closed-loop alignment system.
\item [unidimensional Verniers:] These are the most useful markings for image alignment. For each axis, there are a set of coarse Verniers (bordering the image) and a set of fine Verniers (further from the image) which move 5 times the speed of the coarse Veniers. Every time an image is aligned the white blob will be centered in both the coarse and fine Verniers. These markings essentially amplify and scale the distance between the image (640 microns) and can be used by a motion tracker in a closed-loop alignment system.
\item [multidimenional Verniers:] These are Verniers that are centered in a two-dimenional space everytime an image is focused.
\item [linear Moire grating:] These gratings can be used to make sure that the plates are aligned rotationally (resulting in a completely monochrome bar without any patterns).
\item [circular Moire grating:] These gratings best represent the grid of the images. When an image is aligned the respective grating on the grid will be dark. The number of fringes denotes the accuracy of the alignment (none means perfectly aligned).

@ -0,0 +1,6 @@
\relax
\catcode 95\active
\citation{*}
\bibstyle{unsrt}
\bibdata{hdp}
\gdef \@abspage@last{240}

@ -0,0 +1,286 @@
\documentclass[10pt]{letter}
\usepackage[a4paper, top=0.7in, bottom=0.7in, left=0.7in, right=0.7in]{geometry}
\usepackage{mathtools}
\usepackage{wasysym}
\usepackage{multicol}
\usepackage{dirtree}
\usepackage{underscore}
\usepackage{pdfpages}
\usepackage[framed,numbered]{sclang-prettifier}
\usepackage{listings}
\usepackage[obeyspaces]{url}
\usepackage{datetime2}
%\usepackage{draftwatermark}
\renewcommand{\arraystretch}{1.3}
\usepackage{graphicx}
\usepackage{enumitem}
\DTMsetdatestyle{default}
\DTMsetup{datesep={.}}
%\SetWatermarkColor[rgb]{1, 0.6, 0.6}
%\SetWatermarkScale{2}
%\SetWatermarkHorCenter{1.25in}
%\SetWatermarkVerCenter{1.25in}
% Define Language
\lstdefinelanguage{Lilypond}
{
% list of keywords
morekeywords={
}
}
% Set Language
\lstset{
numbers=left,
numberstyle=\small,
numberstyle = \color{black!33},
numbersep=8pt,
frame = single,
language={Lilypond},
}
\newenvironment{note}{
\vspace{-3mm}
\small
\par
\leftskip=4em\rightskip=5em
\noindent\ignorespaces}{\par\smallskip}
\makeatletter
\newenvironment{thebibliography}[1]
{\list{\@biblabel{\@arabic\c@enumiv}}%
{\settowidth\labelwidth{\@biblabel{#1}}%
\leftmargin\labelwidth
\advance\leftmargin\labelsep
\usecounter{enumiv}%
\let\p@enumiv\@empty
\renewcommand\theenumiv{\@arabic\c@enumiv}}%
\sloppy
\clubpenalty4000
\@clubpenalty \clubpenalty
\widowpenalty4000%
\sfcode`\.\@m}
{\def\@noitemerr
{\@latex@warning{Empty `thebibliography' environment}}%
\endlist}
\newcommand\newblock{\hskip .11em\@plus.33em\@minus.07em}
\makeatother
\begin{document}
\textit{\textbf{a history of the domino problem}} \\
a performance-installation
\begin{flushright}
michael winter \\ schloss solitude and cdmx; 2018 - 2019 \\
\end{flushright}
\bigskip
\begin{center}
\begin{tabular}{cc}
\centering
\includegraphics[width=0.49\linewidth]{selects/maquina.jpg}
\centering
\includegraphics[width=0.49\linewidth]{selects/discos.jpg}
\end{tabular}
\end{center}
\bigskip
\textbf{Description / note}
\textit{a history of the domino problem} is a performance-installation that traces the history of an epistemological problem in mathematics about how things that one could never imagine fitting together, actually come together and unify in unexpected ways. The work comprises a set of musical compositions and a kinetic sculpture that sonify and visualize rare tilings (or mosaics) constructed from dominoes. The dominoes in these tilings are similar yet slightly different than those used in the popular game of the same name. As opposed to rectangles, they are squares with various color combinations along the edges (which can alternatively also be represented by numbers or patterns).\footnote{\url{https://en.wikipedia.org/wiki/Wang_tile}} Like in the game, the rule is that edges of adjacent dominoes in a tiling must match.
The tilings sonified and visualized in \textit{a history of the domino problem} are rare because there is no systematic way to find them. This is due to the fact that they are \textit{aperiodic}.\footnote{\url{https://en.wikipedia.org/wiki/Aperiodic_tiling}} One can think of an aperiodic tiling like an infinite puzzle with a peculiar characteristic. Given unlimited copies of dominoes with a finite set of color/pattern combinations for the edges, there is a solution that will result in a tiling that expands infinitely. However, in that solution, any periodic/repeating structure in the tiling will eventually be interrupted. This phenomenon is one of the most intriguing aspects of the work. As the music and the visuals are derived from the tilings, the resulting textures are always shifting ever so slightly.
The Domino Problem and its corresponding history are somewhat vexing and difficult to describe. The original problem asked if there exists an algorithm/computer program that, when given as input a finite set of dominoes with varying color combinations for the edges, can output a binary answer, `yes' or `no', whether or not copies of that set can form an infinite tiling. The reason why the Domino Problem is inextricably linked to whether or not aperiodic tilings exist is the following. The existence of aperiodic tilings would mean that such an algorithm \textit{does not} exist. The problem was first posed by Hao Wang in 1961. He actually conjectured that aperiodic tilings do not exist. However, in 1966, his student, Robert Berger, proved him wrong by discovering an infinite, aperiodic tiling constructed with copies of a set of 20,426 dominoes. With the original problem solved, mathematicians then took on the challenge of finding the smallest set of dominoes that would construct an infinite aperiodic tiling. Over the past 60 years, this number has been continually reduced until the most recent discovery of a set of 11 dominoes along with a proof that no smaller sets exist. It is a remarkable narrative/history of a particular epistemological problem that challenged a group of people not only to solve it, but to understand it to the extent possible.
The music was composed by writing computer programs that generate and scan the tilings such that musical material and information is correlated with the dominoes. Shifting structures in the tilings are reflected by similarly shifting textures in the music. The musical compositions can act as an accompaniment to the visual component by being performed as interventions within the installation or as singular pieces in concert. The visual component of the piece consists of a kinetic sculpture that displays the tilings using visual cryptography.\footnote{\url{https://en.wikipedia.org/wiki/Visual_cryptography}} In visual cryptography, a message is encrypted by dividing the information of the message into two `shadow' images, each which look completely random independently. The message is decrypted and revealed when the shadow images are combined/overlayed in a precise orientation. The use of visual cryptography to reveal the tilings is yet another reflection of the general motivation of the piece: exploring `how things fit together in unexpected ways'. In \textit{a history of the domino problem}, the message \textit{is} the tilings. The shadow images are printed on photomasks, which are essentially high-resolution transparencies: quartz wafers with a chrome coating etched at a pixel size ranging from nano- to micrometers. I used photomasks for two reasons. One: the Domino Problem is about the limits of computation. What computers can and cannot do. Displaying the tilings using photomasks, which are typically implemented to manufacture computer chips, reflects the concept of the piece through its medium. Two: though the wafers are actually small in size, because they are printed at such high resolution, large portions of the tilings can be displayed. In other words: to go big, sometimes you have to go small. The kinetic sculpture uses a high-precision, motorized multiaxis stage to align the finely printed shadow images and reveal the tilings (along with 3 other images of poetic texts inspired by the history of the Domino Problem). The whole apparatus rests on a light source that illuminates the photomasks, which are then magnified and projected.
\bigskip
\textbf{Installation and performance setting}
As an installation, the apparatus that aligns the image should be centered in a dark room such that observers can view the photomasks up close. Ideally, this should be set up with a teleprompter mirror at a 45 degree angle above the apparatus so that the viewer can see the photomasks without having to bend over. On the other side of the mirror, a video camera is placed such that the resulting projected image aligns with what the viewer sees in the teleprompter mirror. The camera side of the mirror must be darkened out with a cover in order to allow the viewer to only see the reflection of the photomasks. The projection should be as large as possible and at as high a resolution as possible. Ideally, the camera should be able to zoom into the images of the tilings to show more detail.
In the installation, recordings of the musical pieces are played back; sometimes randomly and sometimes in sync with the respective tilings from which they were generated. The installation can be augmented (e.g. for an exhibition opening) by live performances of the musical pieces instead of the recordings. If so, direct access to the apparatus should be avoided in order for a situation where the observers can view the projected images and listen to the musical accompaniment in a tranquil and focused environment.
A demo of the apparatus is available at: \url{https://vimeo.com/375784136}.
\bigskip
\textbf{Photomask alignment}
Between the two photomasks, there are nine embedded images which can be seen at nine precise orientation organized in a 3 x 3 grid. The image area is surrounded by Moire pattern and Vernier markings to aid in the alignment. Provided below are a description of each of these markings.
\begin{center}
\includegraphics[width=0.7\linewidth]{selects/oraclesannotated\string_cp.jpg}
\end{center}
\begin{description}[labelindent=0.5cm]
\item [unidimensional Verniers:] These are the most useful markings for image alignment. For each axis, there are a set of coarse Verniers (bordering the image) and a set of fine Verniers (further from the image) which move 5 times the speed of the coarse Veniers. Every time an image is aligned the white blob will be centered in both the coarse and fine Verniers. These markings essentially amplify and scale the distance between the image (640 microns) and can be used by a motion tracker in a closed-loop alignment system.
\item [multidimenional Verniers:] These are Verniers that are centered in a two-dimenional space everytime an image is focused.
\item [linear Moire grating:] These gratings can be used to make sure that the plates are aligned rotationally (resulting in a completely monochrome bar without any patterns).
\item [circular Moire grating:] These gratings best represent the grid of the images. When an image is aligned the respective grating on the grid will be dark. The number of fringes denotes the accuracy of the alignment (none means perfectly aligned).
\end{description}
High precision optical stages are used for the alignment of the wafers. Ideally, the wafers are not touching (separated by a few microns). If the wafers touch, they will degrade over time as they move across each other. However, it is very difficult to achieve perfect alignment without the photomasks touching as the they need to be aligned in all 6 degrees of freedom ($x$, $y$, $z$, $\theta x$, $\theta y$, and $\theta z$) in order for the resulting image to be properly produced. Only the $x$ and $y$ axis need to be moved to find the images once all the other degrees of freedom are set accurately.
The original setup is as follows. Each of the photomasks are mounted onto tilt stages to be able to align the masks together rotationally (note that a more ideal setup would use goniometer stages). One of the tilt / goniometer stages is then affixed to a stage with 3 degrees of freedom: $x$, $y$, and $z$. The other is fixed directly to an optical breadboard.
To automate the alignment, high precision motors are used to move one of the photomasks on the $x$ and $y$ axes. In the original setup, the high precision motors are stepper motors. If the photomasks are not touching, an open-loop system can be used to automate alignment. That is, the accuracy of the step count of the motors should be sufficient for alignment. However, if the photomasks need to touch in order to produce the resulting images (as is the often the case with the original setup), the friction between the two photomasks will cause inaccuracies in an open-loop system. To compensate for this, the Vernier markings can be tracked optically (using motion-tracking software or opto-interrupts) in order to create a closed-loop system. The software used to automate the system and control the motors is detailed in the following section.
\begin{center}
\includegraphics[width=0.7\linewidth]{selects/maquinalit\string_cp.jpg}
\end{center}
\bigskip
\textbf{Computer code repository and documentation}
As the code is subject to change / improvements, the current state of the is available through a git repository at the following address: \url{https://unboundedpress.org/code/mwinter/a_history_of_the_domino_problem}. The repository contains the computer code needed to run the installation along with all the code that generated the musical pieces and all the code / schematics / files to rebuild the installation. Further, this document along with each of the scores is marked with the date it was generated in order to verify it is the most recent version.
%\textbf{Overview of computer code}
%As the code is subject to change / improvements, the current state of the code is available through a git repository at the following address: \url{https://unboundedpress.org/code/mwinter/a_history_of_the_domino_problem}. The repository contains the computer code needed to run the installation along with all the code that generated the musical pieces and all the code / schematics / files to rebuild the installation. Further, this document along with each of the scores is marked with the date it was generated in order to verify it is the most recent version.
%The repository is organized by the various languages / formats used to generate the musical pieces and visualizations as well as control the installation. To start, I will focus on the software needed to control the installation which includes four basic components:
%\begin{itemize}[labelindent=0.5cm]
%\item A SuperCollider program with the filename \url{installation_control.scd}.
%\item A GUI interface written using Open Stage Control with the filename %\url{installation_control_gui.json}
%\item A motion tracker written in Python using OpenCV to track the Verniers for a closed-loop system with the filename \url{vernier_tracker.py}
%\item Arduino code to communicate between Supercollider and the stepper-motor drivers with the filename\\ \url{multistepper.ino}
%\end{itemize}
%In the original setup, the Arduino code is loaded onto the Arduino and the three other programs are loaded and launched on a computer (e.g., a Raspberry Pi) connected to the Arduino to control the system. The SuperCollider program is the main control center. Both the GUI and the motion tracker (which takes in video input from the video camera) communicate to the SuperCollider program through OSC messages, which, in turn, sends serial messages to the Arduino to control the stepper motors via the stepper motor drivers. The Arduino code not only sends messages to the stepper motor drivers, but also takes input signals from the limit switches of the motors to ensure that the motors are not destroyed by running into a hard stop.
%All the other code (primarily written in SuperCollider) was written to generate the musical pieces as well as the visualizations and is maintained in the repository for reference. For the musical pieces, the SuperCollider code generates electronic realizations of the compositions and Lilypond files for generation of the musical scores.
%The photomasks were printed from the GDSII file format (\url{*.gds}). The workflow consisted of \url{*.png} generated by SuperCollider and then formatted into \url{*.gds} files using the Python KLayout API. However, all that is needed to reprint the photomasks are the files \url{wafer_1.gds} and \url{wafer_2.gds}. Note that the the \url{*.gds} files along with all larger files are archived in a code releases available at \url{https://unboundedpress.org/code/mwinter/a_history_of_the_domino_problem/releases}. Again, all the other files in the repository are maintained for reference.
\bigskip
\newpage
\textbf{Appendix: partial historical timeline of the domino problem, selected bibliography, acknowledgments, and tiling images}
pre-history:\\
\begin{tabular}{p{0.9in}p{1.3in}p{4.0in}}
17th century & Leibniz & pioneer of binary arithmetic and the idea of computing machines \\
ca 1928 & Hilbert & posed the original ``Entsheidungsproblem'' \\
ca 1931 & Goedel & first showed that their exists truths that are undecidable with a finite set of axioms \\
ca 1936 & Turing & invented the concept of the modern day computer and showed its limits yet was unfortunately persecuted for his sexuality despite being a key figure in the triumph of the allied nations against the nazi regime
\end{tabular}
conjecture and first proof:\\
\begin{tabular}{p{0.9in}p{1.3in}p{4.0in}}
ca 1961 & Wang & conjectured that aperiodic tilings of the plane did not exist \\
ca 1966 & Berger & showed that an aperiodic set of 20000+ tiles exist (using his method this was quickly reduced to 104 then 92 by Berger and Knuth, respectively)
\end{tabular}
first wave of reduction:\\
\begin{tabular}{p{0.9in}p{1.3in}p{4.0in}}
ca 1971 & Robinson \& Lauchli & 56 and 40 tiles, respectively; using a similar technique of tiling arbitrarily large squares discovered independently
\end{tabular}
second wave of reduction:\\
\begin{tabular}{p{0.9in}p{1.3in}p{4.0in}}
ca 1986 & Penrose \& Amman & 32 and 16 tiles, respectively; using a method that translates different, non-squared aperiodic tiles into Wang tiles
\end{tabular}
third wave of reduction:\\
\begin{tabular}{p{0.9in}p{1.3in}p{4.0in}}
ca 1996 & Kari \& Culik & 13 tiles using an new construction with aperiodic integer sequences
\end{tabular}
final reduction\\
\begin{tabular}{p{0.9in}p{1.3in}p{4.0in}}
ca 2015 & Jaendel \& Rao & 11 tiles with an incredible computer-assisted proof that no smaller aperiodic sets exist
\end{tabular}
\bigskip
\nocite{*}
\bibliographystyle{unsrt}
\bibliography{hdp}
\bigskip
A special thanks to: Alice Koegel, Ana Filipovic\textsuperscript{$*$}, Angela Butterstein\textsuperscript{}, Anita Carey-Yard\textsuperscript{}, Aykan Safoğlu\textsuperscript{$*$}, Bjoern Gottstein, Charis von Ristok\textsuperscript{}, Christof Pruss, Daniela Kern-Michler\textsuperscript{§}, David Frühauf\textsuperscript{$*$}, David Mathews\textsuperscript{$*$}, Deborah Walker, Denise Helene Sumi\textsuperscript{$*$}, Didier Aschour, Edith Lázár\textsuperscript{$*$}, Elena Morena Weber\textsuperscript{$*$}, Elke aus dem Moore\textsuperscript{}, Elmar Mellert, Florian Hoelscher, Gaetan Borot, Helmut Dietz\textsuperscript{}, Irasema Fernandez, Johanna Markert\textsuperscript{$*$}, Julian Hartbaum\textsuperscript{}, Konstantin Lom\textsuperscript{}, Leon Müllner\textsuperscript{$*$}, Luise Boege\textsuperscript{$*$}, Lukas Ludwig\textsuperscript{$*$}, Luke Wilkins\textsuperscript{$*$}, Marieanne Roth\textsuperscript{}, Mathias Irmsher\textsuperscript{}, Mitra Wakil\textsuperscript{$*$}, Patrizia Bach\textsuperscript{$*$}, Philip Mecke\textsuperscript{$*$}, Robert Blatt\textsuperscript{$*$}, Sander Wickersheim\textsuperscript{}, Savyon\textsuperscript{$*$}, Silke Pflüger\textsuperscript{}, Sílvia das Fadas\textsuperscript{$*$}, Simar Preet Kaur\textsuperscript{$*$}, Sonja Flury\textsuperscript{}, Sophia Guggenberger\textsuperscript{$*$}, Sophie-Charlotte Thieroff\textsuperscript{}, Stephan Martens\textsuperscript{}, Susanna Flock\textsuperscript{$*$}, Tom Rosenberg\textsuperscript{$*$}, Vincenzo Talluto\textsuperscript{§}, and Yuval Shenhar\textsuperscript{$*$}.
* denotes contemporary resident at Akademie Schloss Solitude\\
† denotes Akademie Schloss Solitude staff\\
‡ denotes Institut für Mikroelektronik Stuttgart staff\\
§ denotes Newport Optics staff\\
\vspace{\fill}
\begin{flushright}
version generated: \today
\end{flushright}
\newpage
\vspace*{\fill}
\centering
\includegraphics[width=1\linewidth]{selects/berger\string_cp.jpg}
Berger
\vspace*{\fill}
\newpage
\vspace*{\fill}
\centering
\includegraphics[width=1\linewidth]{selects/robinson\string_cp.jpg}
Robinson
\vspace*{\fill}
\newpage
\vspace*{\fill}
\centering
\includegraphics[width=1\linewidth]{selects/penrose\string_cp.jpg}
Penrose
\vspace*{\fill}
\newpage
\vspace*{\fill}
\centering
\includegraphics[width=1\linewidth]{selects/ammann\string_cp.jpg}
Ammann
\vspace*{\fill}
\newpage
\vspace*{\fill}
\centering
\includegraphics[width=1\linewidth]{selects/kari\string_cp.jpg}
Kari
\vspace*{\fill}
\newpage
\vspace*{\fill}
\centering
\includegraphics[width=1\linewidth]{selects/jaendel\string_cp.jpg}
Jaendel-Rao
\vspace*{\fill}
\includepdf[pages={-}]{../berger/berger\string_score.pdf}
\includepdf[pages={-}]{../robinson/robinson\string_score.pdf}
\includepdf[pages={-}]{../penrose/penrose\string_score.pdf}
\includepdf[pages={-}]{../ammann/ammann\string_score.pdf}
\includepdf[pages={-}]{../kari/kari\string_score.pdf}
\includepdf[pages={-}]{../jaendel/jaendel\string_rao\string_score.pdf}
\end{document}

@ -0,0 +1,6 @@
\relax
\catcode 95\active
\citation{*}
\bibstyle{unsrt}
\bibdata{hdp}
\gdef \@abspage@last{78}

@ -0,0 +1,295 @@
\documentclass[10pt]{letter}
\usepackage[a4paper, top=0.7in, bottom=0.7in, left=0.7in, right=0.7in]{geometry}
\usepackage{mathtools}
\usepackage{wasysym}
\usepackage{multicol}
\usepackage{dirtree}
\usepackage{underscore}
\usepackage{pdfpages}
\usepackage[framed,numbered]{sclang-prettifier}
\usepackage{listings}
\usepackage[obeyspaces]{url}
\usepackage{datetime2}
%\usepackage{draftwatermark}
\renewcommand{\arraystretch}{1.3}
\usepackage{graphicx}
\usepackage{enumitem}
\DTMsetdatestyle{default}
\DTMsetup{datesep={.}}
%\SetWatermarkColor[rgb]{1, 0.6, 0.6}
%\SetWatermarkScale{2}
%\SetWatermarkHorCenter{1.25in}
%\SetWatermarkVerCenter{1.25in}
% Define Language
\lstdefinelanguage{Lilypond}
{
% list of keywords
morekeywords={
}
}
% Set Language
\lstset{
numbers=left,
numberstyle=\small,
numberstyle = \color{black!33},
numbersep=8pt,
frame = single,
language={Lilypond},
}
\newenvironment{note}{
\vspace{-3mm}
\small
\par
\leftskip=4em\rightskip=5em
\noindent\ignorespaces}{\par\smallskip}
\makeatletter
\newenvironment{thebibliography}[1]
{\list{\@biblabel{\@arabic\c@enumiv}}%
{\settowidth\labelwidth{\@biblabel{#1}}%
\leftmargin\labelwidth
\advance\leftmargin\labelsep
\usecounter{enumiv}%
\let\p@enumiv\@empty
\renewcommand\theenumiv{\@arabic\c@enumiv}}%
\sloppy
\clubpenalty4000
\@clubpenalty \clubpenalty
\widowpenalty4000%
\sfcode`\.\@m}
{\def\@noitemerr
{\@latex@warning{Empty `thebibliography' environment}}%
\endlist}
\newcommand\newblock{\hskip .11em\@plus.33em\@minus.07em}
\makeatother
\begin{document}
\textit{\textbf{a history of the domino problem}} \\
a performance-installation
\begin{flushright}
michael winter \\ schloss solitude and cdmx; 2018 - 2019 \\
\end{flushright}
\bigskip
\begin{center}
\begin{tabular}{cc}
\centering
\includegraphics[width=0.49\linewidth]{selects/maquina.jpg}
\centering
\includegraphics[width=0.49\linewidth]{selects/discos.jpg}
\end{tabular}
\end{center}
\bigskip
\textbf{Description / note}
\textit{a history of the domino problem} is a performance-installation that traces the history of an epistemological problem in mathematics about how things that one could never imagine fitting together, actually come together and unify in unexpected ways. The work comprises a set of musical compositions and a kinetic sculpture that sonify and visualize rare tilings (or mosaics) constructed from dominoes. The dominoes in these tilings are similar yet slightly different than those used in the popular game of the same name. As opposed to rectangles, they are squares with various color combinations along the edges (which can alternatively also be represented by numbers or patterns).\footnote{\url{https://en.wikipedia.org/wiki/Wang_tile}} Like in the game, the rule is that edges of adjacent dominoes in a tiling must match.
The tilings sonified and visualized in \textit{a history of the domino problem} are rare because there is no systematic way to find them. This is due to the fact that they are \textit{aperiodic}.\footnote{\url{https://en.wikipedia.org/wiki/Aperiodic_tiling}} One can think of an aperiodic tiling like an infinite puzzle with a peculiar characteristic. Given unlimited copies of dominoes with a finite set of color/pattern combinations for the edges, there is a solution that will result in a tiling that expands infinitely. However, in that solution, any periodic/repeating structure in the tiling will eventually be interrupted. This phenomenon is one of the most intriguing aspects of the work. As the music and the visuals are derived from the tilings, the resulting textures are always shifting ever so slightly.
The Domino Problem and its corresponding history are somewhat vexing and difficult to describe. The original problem asked if there exists an algorithm/computer program that, when given as input a finite set of dominoes with varying color combinations for the edges, can output a binary answer, `yes' or `no', whether or not copies of that set can form an infinite tiling. The reason why the Domino Problem is inextricably linked to whether or not aperiodic tilings exist is the following. The existence of aperiodic tilings would mean that such an algorithm \textit{does not} exist. The problem was first posed by Hao Wang in 1961. He actually conjectured that aperiodic tilings do not exist. However, in 1966, his student, Robert Berger, proved him wrong by discovering an infinite, aperiodic tiling constructed with copies of a set of 20,426 dominoes. With the original problem solved, mathematicians then took on the challenge of finding the smallest set of dominoes that would construct an infinite aperiodic tiling. Over the past 60 years, this number has been continually reduced until the most recent discovery of a set of 11 dominoes along with a proof that no smaller sets exist. It is a remarkable narrative/history of a particular epistemological problem that challenged a group of people not only to solve it, but to understand it to the extent possible.
The music was composed by writing computer programs that generate and scan the tilings such that musical material and information is correlated with the dominoes. Shifting structures in the tilings are reflected by similarly shifting textures in the music. The musical compositions can act as an accompaniment to the visual component by being performed as interventions within the installation or as singular pieces in concert. The visual component of the piece consists of a kinetic sculpture that displays the tilings using visual cryptography.\footnote{\url{https://en.wikipedia.org/wiki/Visual_cryptography}} In visual cryptography, a message is encrypted by dividing the information of the message into two `shadow' images, each which look completely random independently. The message is decrypted and revealed when the shadow images are combined/overlayed in a precise orientation. The use of visual cryptography to reveal the tilings is yet another reflection of the general motivation of the piece: exploring `how things fit together in unexpected ways'. In \textit{a history of the domino problem}, the message \textit{is} the tilings. The shadow images are printed on photomasks, which are essentially high-resolution transparencies: quartz wafers with a chrome coating etched at a pixel size ranging from nano- to micrometers. I used photomasks for two reasons. One: the Domino Problem is about the limits of computation. What computers can and cannot do. Displaying the tilings using photomasks, which are typically implemented to manufacture computer chips, reflects the concept of the piece through its medium. Two: though the wafers are actually small in size, because they are printed at such high resolution, large portions of the tilings can be displayed. In other words: to go big, sometimes you have to go small. The kinetic sculpture uses a high-precision, motorized multiaxis stage to align the finely printed shadow images and reveal the tilings (along with 3 other images of poetic texts inspired by the history of the Domino Problem). The whole apparatus rests on a light source that illuminates the photomasks, which are then magnified and projected.
\bigskip
\textbf{Installation and performance setting}
As an installation, the apparatus that aligns the image should be centered in a dark room such that observers can view the photomasks up close. Ideally, this should be set up with a teleprompter mirror at a 45 degree angle above the apparatus so that the viewer can see the photomasks without having to bend over. On the other side of the mirror, a video camera is placed such that the resulting projected image aligns with what the viewer sees in the teleprompter mirror. The camera side of the mirror must be darkened out with a cover in order to allow the viewer to only see the reflection of the photomasks. The projection should be as large as possible and at as high a resolution as possible. Ideally, the camera should be able to zoom into the images of the tilings to show more detail.
In the installation, recordings of the musical pieces are played back; sometimes randomly and sometimes in sync with the respective tilings from which they were generated. The installation can be augmented (e.g. for an exhibition opening) by live performances of the musical pieces instead of the recordings. If so, direct access to the apparatus should be avoided in order for a situation where the observers can view the projected images and listen to the musical accompaniment in a tranquil and focused environment.
A demo of the apparatus is available at: \url{https://vimeo.com/375784136}.
\bigskip
\textbf{Photomask alignment}
Between the two photomasks, there are nine embedded images which can be seen at nine precise orientation organized in a 3 x 3 grid. The image area is surrounded by Moire pattern and Vernier markings to aid in the alignment. Provided below are a description of each of these markings.
\begin{center}
\includegraphics[width=0.7\linewidth]{selects/oraclesannotated\string_cp.jpg}
\end{center}
\begin{description}[labelindent=0.5cm]
\item [unidimensional Verniers:] These are the most useful markings for image alignment. For each axis, there are a set of coarse Verniers (bordering the image) and a set of fine Verniers (further from the image) which move 5 times the speed of the coarse Veniers. Every time an image is aligned the white blob will be centered in both the coarse and fine Verniers. These markings essentially amplify and scale the distance between the image (640 microns) and can be used by a motion tracker in a closed-loop alignment system.
\item [multidimenional Verniers:] These are Verniers that are centered in a two-dimenional space everytime an image is focused.
\item [linear Moire grating:] These gratings can be used to make sure that the plates are aligned rotationally (resulting in a completely monochrome bar without any patterns).
\item [circular Moire grating:] These gratings best represent the grid of the images. When an image is aligned the respective grating on the grid will be dark. The number of fringes denotes the accuracy of the alignment (none means perfectly aligned).
\end{description}
High precision optical stages are used for the alignment of the wafers. Ideally, the wafers are not touching (separated by a few microns). If the wafers touch, they will degrade over time as they move across each other. However, it is very difficult to achieve perfect alignment without the photomasks touching as the they need to be aligned in all 6 degrees of freedom ($x$, $y$, $z$, $\theta x$, $\theta y$, and $\theta z$) in order for the resulting image to be properly produced. Only the $x$ and $y$ axis need to be moved to find the images once all the other degrees of freedom are set accurately.
The original setup is as follows. Each of the photomasks are mounted onto tilt stages to be able to align the masks together rotationally (note that a more ideal setup would use goniometer stages). One of the tilt / goniometer stages is then affixed to a stage with 3 degrees of freedom: $x$, $y$, and $z$. The other is fixed directly to an optical breadboard.
To automate the alignment, high precision motors are used to move one of the photomasks on the $x$ and $y$ axes. In the original setup, the high precision motors are stepper motors. If the photomasks are not touching, an open-loop system can be used to automate alignment. That is, the accuracy of the step count of the motors should be sufficient for alignment. However, if the photomasks need to touch in order to produce the resulting images (as is the often the case with the original setup), the friction between the two photomasks will cause inaccuracies in an open-loop system. To compensate for this, the Vernier markings can be tracked optically (using motion-tracking software or opto-interrupts) in order to create a closed-loop system. The software used to automate the system and control the motors is detailed in the following section.
\begin{center}
\includegraphics[width=0.7\linewidth]{selects/maquinalit\string_cp.jpg}
\end{center}
\bigskip
\textbf{Computer code repository and documentation}
As the code is subject to change / improvements, the current state of the is available through a git repository at the following address: \url{https://unboundedpress.org/code/mwinter/a_history_of_the_domino_problem}. The repository contains the computer code needed to run the installation along with all the code that generated the musical pieces and all the code / schematics / files to rebuild the installation. Further, this document along with each of the scores is marked with the date it was generated in order to verify it is the most recent version.
%\textbf{Overview of computer code}
%As the code is subject to change / improvements, the current state of the code is available through a git repository at the following address: \url{https://unboundedpress.org/code/mwinter/a_history_of_the_domino_problem}. The repository contains the computer code needed to run the installation along with all the code that generated the musical pieces and all the code / schematics / files to rebuild the installation. Further, this document along with each of the scores is marked with the date it was generated in order to verify it is the most recent version.
%The repository is organized by the various languages / formats used to generate the musical pieces and visualizations as well as control the installation. To start, I will focus on the software needed to control the installation which includes four basic components:
%\begin{itemize}[labelindent=0.5cm]
%\item A SuperCollider program with the filename \url{installation_control.scd}.
%\item A GUI interface written using Open Stage Control with the filename %\url{installation_control_gui.json}
%\item A motion tracker written in Python using OpenCV to track the Verniers for a closed-loop system with the filename \url{vernier_tracker.py}
%\item Arduino code to communicate between Supercollider and the stepper-motor drivers with the filename\\ \url{multistepper.ino}
%\end{itemize}
%In the original setup, the Arduino code is loaded onto the Arduino and the three other programs are loaded and launched on a computer (e.g., a Raspberry Pi) connected to the Arduino to control the system. The SuperCollider program is the main control center. Both the GUI and the motion tracker (which takes in video input from the video camera) communicate to the SuperCollider program through OSC messages, which, in turn, sends serial messages to the Arduino to control the stepper motors via the stepper motor drivers. The Arduino code not only sends messages to the stepper motor drivers, but also takes input signals from the limit switches of the motors to ensure that the motors are not destroyed by running into a hard stop.
%All the other code (primarily written in SuperCollider) was written to generate the musical pieces as well as the visualizations and is maintained in the repository for reference. For the musical pieces, the SuperCollider code generates electronic realizations of the compositions and Lilypond files for generation of the musical scores.
%The photomasks were printed from the GDSII file format (\url{*.gds}). The workflow consisted of \url{*.png} generated by SuperCollider and then formatted into \url{*.gds} files using the Python KLayout API. However, all that is needed to reprint the photomasks are the files \url{wafer_1.gds} and \url{wafer_2.gds}. Note that the the \url{*.gds} files along with all larger files are archived in a code releases available at \url{https://unboundedpress.org/code/mwinter/a_history_of_the_domino_problem/releases}. Again, all the other files in the repository are maintained for reference.
\bigskip
\newpage
\textbf{Appendix: partial historical timeline of the domino problem, selected bibliography, acknowledgments, and tiling images}
pre-history:\\
\begin{tabular}{p{0.9in}p{1.3in}p{4.0in}}
17th century & Leibniz & pioneer of binary arithmetic and the idea of computing machines \\
ca 1928 & Hilbert & posed the original ``Entsheidungsproblem'' \\
ca 1931 & Goedel & first showed that their exists truths that are undecidable with a finite set of axioms \\
ca 1936 & Turing & invented the concept of the modern day computer and showed its limits yet was unfortunately persecuted for his sexuality despite being a key figure in the triumph of the allied nations against the nazi regime
\end{tabular}
conjecture and first proof:\\
\begin{tabular}{p{0.9in}p{1.3in}p{4.0in}}
ca 1961 & Wang & conjectured that aperiodic tilings of the plane did not exist \\
ca 1966 & Berger & showed that an aperiodic set of 20000+ tiles exist (using his method this was quickly reduced to 104 then 92 by Berger and Knuth, respectively)
\end{tabular}
first wave of reduction:\\
\begin{tabular}{p{0.9in}p{1.3in}p{4.0in}}
ca 1971 & Robinson \& Lauchli & 56 and 40 tiles, respectively; using a similar technique of tiling arbitrarily large squares discovered independently
\end{tabular}
second wave of reduction:\\
\begin{tabular}{p{0.9in}p{1.3in}p{4.0in}}
ca 1986 & Penrose \& Amman & 32 and 16 tiles, respectively; using a method that translates different, non-squared aperiodic tiles into Wang tiles
\end{tabular}
third wave of reduction:\\
\begin{tabular}{p{0.9in}p{1.3in}p{4.0in}}
ca 1996 & Kari \& Culik & 13 tiles using an new construction with aperiodic integer sequences
\end{tabular}
final reduction\\
\begin{tabular}{p{0.9in}p{1.3in}p{4.0in}}
ca 2015 & Jaendel \& Rao & 11 tiles with an incredible computer-assisted proof that no smaller aperiodic sets exist
\end{tabular}
\bigskip
\nocite{*}
\bibliographystyle{unsrt}
\bibliography{hdp}
\bigskip
A special thanks to: Alice Koegel, Ana Filipovic\textsuperscript{$*$}, Angela Butterstein\textsuperscript{}, Anita Carey-Yard\textsuperscript{}, Aykan Safoğlu\textsuperscript{$*$}, Bjoern Gottstein, Charis von Ristok\textsuperscript{}, Christof Pruss, Daniela Kern-Michler\textsuperscript{§}, David Frühauf\textsuperscript{$*$}, David Mathews\textsuperscript{$*$}, Deborah Walker, Denise Helene Sumi\textsuperscript{$*$}, Didier Aschour, Edith Lázár\textsuperscript{$*$}, Elena Morena Weber\textsuperscript{$*$}, Elke aus dem Moore\textsuperscript{}, Elmar Mellert, Florian Hoelscher, Gaetan Borot, Helmut Dietz\textsuperscript{}, Irasema Fernandez, Johanna Markert\textsuperscript{$*$}, Julian Hartbaum\textsuperscript{}, Konstantin Lom\textsuperscript{}, Leon Müllner\textsuperscript{$*$}, Luise Boege\textsuperscript{$*$}, Lukas Ludwig\textsuperscript{$*$}, Luke Wilkins\textsuperscript{$*$}, Marieanne Roth\textsuperscript{}, Mathias Irmsher\textsuperscript{}, Mitra Wakil\textsuperscript{$*$}, Patrizia Bach\textsuperscript{$*$}, Philip Mecke\textsuperscript{$*$}, Robert Blatt\textsuperscript{$*$}, Sander Wickersheim\textsuperscript{}, Savyon\textsuperscript{$*$}, Silke Pflüger\textsuperscript{}, Sílvia das Fadas\textsuperscript{$*$}, Simar Preet Kaur\textsuperscript{$*$}, Sonja Flury\textsuperscript{}, Sophia Guggenberger\textsuperscript{$*$}, Sophie-Charlotte Thieroff\textsuperscript{}, Stephan Martens\textsuperscript{}, Susanna Flock\textsuperscript{$*$}, Tom Rosenberg\textsuperscript{$*$}, Vincenzo Talluto\textsuperscript{§}, and Yuval Shenhar\textsuperscript{$*$}.
* denotes contemporary resident at Akademie Schloss Solitude\\
† denotes Akademie Schloss Solitude staff\\
‡ denotes Institut für Mikroelektronik Stuttgart staff\\
§ denotes Newport Optics staff\\
\vspace{\fill}
\begin{flushright}
version generated: \today
\end{flushright}
\newpage
\vspace*{\fill}
\centering
\includegraphics[width=1\linewidth]{selects/berger\string_cp.jpg}
Berger
\vspace*{\fill}
\newpage
\vspace*{\fill}
\centering
\includegraphics[width=1\linewidth]{selects/robinson\string_cp.jpg}
Robinson
\vspace*{\fill}
\newpage
\vspace*{\fill}
\centering
\includegraphics[width=1\linewidth]{selects/penrose\string_cp.jpg}
Penrose
\vspace*{\fill}
\newpage
\vspace*{\fill}
\centering
\includegraphics[width=1\linewidth]{selects/ammann\string_cp.jpg}
Ammann
\vspace*{\fill}
\newpage
\vspace*{\fill}
\centering
\includegraphics[width=1\linewidth]{selects/kari\string_cp.jpg}
Kari
\vspace*{\fill}
\newpage
\vspace*{\fill}
\centering
\includegraphics[width=1\linewidth]{selects/jaendel\string_cp.jpg}
Jaendel-Rao
\vspace*{\fill}
\includepdf[pages={1-1}]{../berger/berger\string_score.pdf}
\includepdf[pages={-7}]{../../score/lilypond\string_v2.24\string_update/berger\string_knuth/berger\string_knuth\string_merge\string_for\string_kali.pdf}
\includepdf[pages={1-1}]{../robinson/robinson\string_score.pdf}
\includepdf[pages={-15}]{../../score/lilypond\string_v2.24\string_update/robinson/robinson\string_no\string_alto.pdf}
\includepdf[pages={1-1}]{../penrose/penrose\string_score.pdf}
\includepdf[pages={-19}]{../../score/lilypond\string_v2.24\string_update/penrose/penrose\string_no\string_alto.pdf}
\includepdf[pages={1-1}]{../ammann/ammann\string_score.pdf}
\includepdf[pages={-6}]{../../score/lilypond\string_v2.24\string_update/ammann\string_distributed/ammann\string_distributed.pdf}
\includepdf[pages={-}]{../kari/kari\string_score.pdf}
\includepdf[pages={1-1}]{../jaendel/jaendel\string_rao\string_score.pdf}
\end{document}

@ -1,2 +1,3 @@
\relax
\catcode 95\active
\gdef \@abspage@last{36}

File diff suppressed because it is too large Load Diff

@ -6,18 +6,18 @@
\usepackage{verbatim}
\usepackage{pdfpages}
\usepackage{datetime2}
\usepackage{draftwatermark}
%\usepackage{draftwatermark}
\usepackage{graphicx}
\DTMsetdatestyle{default}
\DTMsetup{datesep={.}}
\SetWatermarkColor[rgb]{1, 0.6, 0.6}
\SetWatermarkScale{2}
\SetWatermarkHorCenter{4in}
\SetWatermarkVerCenter{4in}
\SetWatermarkText{UNFINISHED DRAFT}
\SetWatermarkText{}
%\SetWatermarkColor[rgb]{1, 0.6, 0.6}
%\SetWatermarkScale{2}
%\SetWatermarkHorCenter{4in}
%\SetWatermarkVerCenter{4in}
%\SetWatermarkText{UNFINISHED DRAFT}
%\SetWatermarkText{}
\begin{document}
\thispagestyle{empty}
@ -26,13 +26,13 @@
\textit{\textbf{ammann}} \\
\normalsize
from \textit{a history of the domino problem}\\
for 5 to 8 sustaining instruments
for 4 to 8 sustaining instruments
\bigskip
\bigskip
\normalsize
The ensemble can play any 5 or more parts (preferably as many as possible) and any 8 or more adjacent sections. If the ensemble starts after the first section (the 2nd through 13th sections), the performers should start on the first note that has an onset within the first measure of the section (replacing the tied note from the last measure of the previous section with a rest). If ending before the final section (the 8th through 19th sections), the last note of each part should be the note tied over from the penultimate measure of the section. Each part should be as distinct in timbre as possible.
The ensemble can play any 4 or more parts (preferably as many as possible) and any 6 or more adjacent sections. If the ensemble starts after the first section (the 2nd through 13th sections), the performers should start on the first note that has an onset within the first measure of the section (replacing the tied note from the last measure of the previous section with a rest). If ending before the final section (the 8th through 19th sections), the last note of each part should be the note tied over from the penultimate measure of the section. Each part should be as distinct in timbre as possible.
All the parts are notated within one octave. Written above each note is an up or down arrow indicating whether the pitch be played high or low. That is, in each part, each pitch-class can occur in one of two ways: in either a higher register or a lower one (the up / down arrows should be interpreted in the same respective register throughout). Which registers are selected for each note in each part is open, but should be selected such that there is some overlap / pitch duplications among the parts and some separation. Limiting the overlap will naturally stratify the registers of the parts. The part number should generally correspond to its relative register (i.e. part 2 should be generally higher than part 1). The ensemble can explore replacing pitches of one to two of the parts with various non-pitched percussion instruments with relatively long decays. The up and down arrows would then be interpreted as two different types of the same instrument (e.g. two sizes of triangles).
@ -56,7 +56,7 @@ michael winter\\
version generated: \today
\end{flushright}
\includepdf[pages={-}]{../../score/lilypond/ammann/ammann.pdf}
\includepdf[pages={-}]{../../score/lilypond\string_v2.24\string_update/ammann/ammann.pdf}
\end{document}

@ -1,2 +1,3 @@
\relax
\catcode 95\active
\gdef \@abspage@last{16}

@ -1,186 +1,178 @@
This is pdfTeX, Version 3.14159265-2.6-1.40.20 (TeX Live 2019/Arch Linux) (preloaded format=pdflatex 2019.9.6) 6 DEC 2019 18:28
This is pdfTeX, Version 3.141592653-2.6-1.40.25 (TeX Live 2023/Arch Linux) (preloaded format=pdflatex 2023.7.4) 20 JUL 2023 18:30
entering extended mode
restricted \write18 enabled.
\write18 enabled.
%&-line parsing enabled.
**kari_score.tex
(./kari_score.tex
LaTeX2e <2018-12-01>
LaTeX2e <2022-11-01> patch level 1
L3 programming layer <2023-02-22>
(/usr/share/texmf-dist/tex/latex/base/letter.cls
Document Class: letter 2014/09/29 v1.2z Standard LaTeX document class
Document Class: letter 2021/12/07 v1.3c Standard LaTeX document class
(/usr/share/texmf-dist/tex/latex/base/size10.clo
File: size10.clo 2018/09/03 v1.4i Standard LaTeX file (size option)
File: size10.clo 2022/07/02 v1.4n Standard LaTeX file (size option)
)
\longindentation=\dimen102
\indentedwidth=\dimen103
\labelcount=\count80
\longindentation=\dimen140
\indentedwidth=\dimen141
\labelcount=\count185
)
(/usr/share/texmf-dist/tex/latex/geometry/geometry.sty
Package: geometry 2018/04/16 v5.8 Page Geometry
Package: geometry 2020/01/02 v5.9 Page Geometry
(/usr/share/texmf-dist/tex/latex/graphics/keyval.sty
Package: keyval 2014/10/28 v1.15 key=value parser (DPC)
\KV@toks@=\toks14
Package: keyval 2022/05/29 v1.15 key=value parser (DPC)
\KV@toks@=\toks16
)
(/usr/share/texmf-dist/tex/generic/oberdiek/ifpdf.sty
Package: ifpdf 2018/09/07 v3.3 Provides the ifpdf switch
)
(/usr/share/texmf-dist/tex/generic/oberdiek/ifvtex.sty
Package: ifvtex 2016/05/16 v1.6 Detect VTeX and its facilities (HO)
Package ifvtex Info: VTeX not detected.
)
(/usr/share/texmf-dist/tex/generic/ifxetex/ifxetex.sty
Package: ifxetex 2010/09/12 v0.6 Provides ifxetex conditional
)
\Gm@cnth=\count81
\Gm@cntv=\count82
\c@Gm@tempcnt=\count83
\Gm@bindingoffset=\dimen104
\Gm@wd@mp=\dimen105
\Gm@odd@mp=\dimen106
\Gm@even@mp=\dimen107
\Gm@layoutwidth=\dimen108
\Gm@layoutheight=\dimen109
\Gm@layouthoffset=\dimen110
\Gm@layoutvoffset=\dimen111
\Gm@dimlist=\toks15
(/usr/share/texmf-dist/tex/generic/iftex/ifvtex.sty
Package: ifvtex 2019/10/25 v1.7 ifvtex legacy package. Use iftex instead.
(/usr/share/texmf-dist/tex/generic/iftex/iftex.sty
Package: iftex 2022/02/03 v1.0f TeX engine tests
))
\Gm@cnth=\count186
\Gm@cntv=\count187
\c@Gm@tempcnt=\count188
\Gm@bindingoffset=\dimen142
\Gm@wd@mp=\dimen143
\Gm@odd@mp=\dimen144
\Gm@even@mp=\dimen145
\Gm@layoutwidth=\dimen146
\Gm@layoutheight=\dimen147
\Gm@layouthoffset=\dimen148
\Gm@layoutvoffset=\dimen149
\Gm@dimlist=\toks17
)
(/usr/share/texmf-dist/tex/latex/underscore/underscore.sty
Package: underscore 2006/09/13
LaTeX Info: Redefining \_ on input line 42.
)
(/usr/share/texmf-dist/tex/latex/url/url.sty
\Urlmuskip=\muskip10
\Urlmuskip=\muskip16
Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc.
)
(/usr/share/texmf-dist/tex/latex/tools/verbatim.sty
Package: verbatim 2014/10/28 v1.5q LaTeX2e package for verbatim enhancements
\every@verbatim=\toks16
\verbatim@line=\toks17
\verbatim@in@stream=\read1
Package: verbatim 2022-07-02 v1.5u LaTeX2e package for verbatim enhancements
\every@verbatim=\toks18
\verbatim@line=\toks19
\verbatim@in@stream=\read2
)
(/usr/share/texmf-dist/tex/latex/pdfpages/pdfpages.sty
Package: pdfpages 2017/10/31 v0.5l Insert pages of external PDF documents (AM)
Package: pdfpages 2022/12/19 v0.5x Insert pages of external PDF documents (AM)
(/usr/share/texmf-dist/tex/latex/base/ifthen.sty
Package: ifthen 2014/09/29 v1.1c Standard LaTeX ifthen package (DPC)
Package: ifthen 2022/04/13 v1.1d Standard LaTeX ifthen package (DPC)
)
(/usr/share/texmf-dist/tex/latex/tools/calc.sty
Package: calc 2017/05/25 v4.3 Infix arithmetic (KKT,FJ)
\calc@Acount=\count84
\calc@Bcount=\count85
\calc@Adimen=\dimen112
\calc@Bdimen=\dimen113
\calc@Askip=\skip41
\calc@Bskip=\skip42
\calc@Acount=\count189
\calc@Bcount=\count190
\calc@Adimen=\dimen150
\calc@Bdimen=\dimen151
\calc@Askip=\skip48
\calc@Bskip=\skip49
LaTeX Info: Redefining \setlength on input line 80.
LaTeX Info: Redefining \addtolength on input line 81.
\calc@Ccount=\count86
\calc@Cskip=\skip43
\calc@Ccount=\count191
\calc@Cskip=\skip50
)
(/usr/share/texmf-dist/tex/latex/eso-pic/eso-pic.sty
Package: eso-pic 2018/04/12 v2.0h eso-pic (RN)
(/usr/share/texmf-dist/tex/generic/oberdiek/atbegshi.sty
Package: atbegshi 2016/06/09 v1.18 At begin shipout hook (HO)
Package: eso-pic 2020/10/14 v3.0a eso-pic (RN)
\ESO@tempdima=\dimen152
\ESO@tempdimb=\dimen153
(/usr/share/texmf-dist/tex/generic/oberdiek/infwarerr.sty
Package: infwarerr 2016/05/16 v1.4 Providing info/warning/error messages (HO)
)
(/usr/share/texmf-dist/tex/generic/oberdiek/ltxcmds.sty
Package: ltxcmds 2016/05/16 v1.23 LaTeX kernel commands for general use (HO)
))
(/usr/share/texmf-dist/tex/latex/xcolor/xcolor.sty
Package: xcolor 2016/05/11 v2.12 LaTeX color extensions (UK)
Package: xcolor 2022/06/12 v2.14 LaTeX color extensions (UK)
(/usr/share/texmf-dist/tex/latex/graphics-cfg/color.cfg
File: color.cfg 2016/01/02 v1.6 sample color configuration
)
Package xcolor Info: Driver file: pdftex.def on input line 225.
Package xcolor Info: Driver file: pdftex.def on input line 227.
(/usr/share/texmf-dist/tex/latex/graphics-def/pdftex.def
File: pdftex.def 2018/01/08 v1.0l Graphics/color driver for pdftex
File: pdftex.def 2022/09/22 v1.2b Graphics/color driver for pdftex
)
Package xcolor Info: Model `cmy' substituted by `cmy0' on input line 1348.
Package xcolor Info: Model `hsb' substituted by `rgb' on input line 1352.
Package xcolor Info: Model `RGB' extended on input line 1364.
Package xcolor Info: Model `HTML' substituted by `rgb' on input line 1366.
Package xcolor Info: Model `Hsb' substituted by `hsb' on input line 1367.
Package xcolor Info: Model `tHsb' substituted by `hsb' on input line 1368.
Package xcolor Info: Model `HSB' substituted by `hsb' on input line 1369.
Package xcolor Info: Model `Gray' substituted by `gray' on input line 1370.
Package xcolor Info: Model `wave' substituted by `hsb' on input line 1371.
(/usr/share/texmf-dist/tex/latex/graphics/mathcolor.ltx)
Package xcolor Info: Model `cmy' substituted by `cmy0' on input line 1353.
Package xcolor Info: Model `hsb' substituted by `rgb' on input line 1357.
Package xcolor Info: Model `RGB' extended on input line 1369.
Package xcolor Info: Model `HTML' substituted by `rgb' on input line 1371.
Package xcolor Info: Model `Hsb' substituted by `hsb' on input line 1372.
Package xcolor Info: Model `tHsb' substituted by `hsb' on input line 1373.
Package xcolor Info: Model `HSB' substituted by `hsb' on input line 1374.
Package xcolor Info: Model `Gray' substituted by `gray' on input line 1375.
Package xcolor Info: Model `wave' substituted by `hsb' on input line 1376.
))
(/usr/share/texmf-dist/tex/latex/graphics/graphicx.sty
Package: graphicx 2017/06/01 v1.1a Enhanced LaTeX Graphics (DPC,SPQR)
Package: graphicx 2021/09/16 v1.2d Enhanced LaTeX Graphics (DPC,SPQR)
(/usr/share/texmf-dist/tex/latex/graphics/graphics.sty
Package: graphics 2017/06/25 v1.2c Standard LaTeX Graphics (DPC,SPQR)
Package: graphics 2022/03/10 v1.4e Standard LaTeX Graphics (DPC,SPQR)
(/usr/share/texmf-dist/tex/latex/graphics/trig.sty
Package: trig 2016/01/03 v1.10 sin cos tan (DPC)
Package: trig 2021/08/11 v1.11 sin cos tan (DPC)
)
(/usr/share/texmf-dist/tex/latex/graphics-cfg/graphics.cfg
File: graphics.cfg 2016/06/04 v1.11 sample graphics configuration
)
Package graphics Info: Driver file: pdftex.def on input line 99.
Package graphics Info: Driver file: pdftex.def on input line 107.
)
\Gin@req@height=\dimen114
\Gin@req@width=\dimen115
\Gin@req@height=\dimen154
\Gin@req@width=\dimen155
)
\AM@pagewidth=\dimen116
\AM@pageheight=\dimen117
\AM@pagewidth=\dimen156
\AM@pageheight=\dimen157
\AM@fboxrule=\dimen158
(/usr/share/texmf-dist/tex/latex/pdfpages/pppdftex.def
File: pppdftex.def 2017/10/31 v0.5l Pdfpages driver for pdfTeX (AM)
File: pppdftex.def 2022/12/19 v0.5x Pdfpages driver for pdfTeX (AM)
)
\AM@pagebox=\box27
\AM@global@opts=\toks18
\AM@toc@title=\toks19
\c@AM@survey=\count87
\AM@templatesizebox=\box28
\pdfpages@includegraphics@status=\count192
\AM@pagebox=\box51
\AM@global@opts=\toks20
\AM@pagecnt=\count193
\AM@toc@title=\toks21
\AM@lof@heading=\toks22
\c@AM@survey=\count194
\AM@templatesizebox=\box52
)
(/usr/share/texmf-dist/tex/latex/datetime2/datetime2.sty
Package: datetime2 2018/07/20 v1.5.3 (NLCT) date and time formats
Package: datetime2 2021/03/21 v1.5.7 (NLCT) date and time formats
(/usr/share/texmf-dist/tex/latex/tracklang/tracklang.sty
Package: tracklang 2018/05/13 v1.3.6 (NLCT) Track Languages
Package: tracklang 2022/12/13 v1.6.1 (NLCT) Track Languages
(/usr/share/texmf-dist/tex/generic/tracklang/tracklang.tex))
(/usr/share/texmf-dist/tex/latex/etoolbox/etoolbox.sty
Package: etoolbox 2018/08/19 v2.5f e-TeX tools for LaTeX (JAW)
\etb@tempcnta=\count88
Package: etoolbox 2020/10/05 v2.5k e-TeX tools for LaTeX (JAW)
\etb@tempcnta=\count195
)
(/usr/share/texmf-dist/tex/latex/xkeyval/xkeyval.sty
Package: xkeyval 2014/12/03 v2.7a package option processing (HA)
Package: xkeyval 2022/06/16 v2.9 package option processing (HA)
(/usr/share/texmf-dist/tex/generic/xkeyval/xkeyval.tex
(/usr/share/texmf-dist/tex/generic/xkeyval/xkvutils.tex
\XKV@toks=\toks20
\XKV@tempa@toks=\toks21
\XKV@toks=\toks23
\XKV@tempa@toks=\toks24
)
\XKV@depth=\count89
\XKV@depth=\count196
File: xkeyval.tex 2014/12/03 v2.7a key=value parser (HA)
)))
(/usr/share/texmf-dist/tex/latex/draftwatermark/draftwatermark.sty
Package: draftwatermark 2015/02/19 1.2 Put a gray textual watermark on document
pages
(/usr/share/texmf-dist/tex/latex/everypage/everypage.sty
Package: everypage 2007/06/20 1.1 Hooks to run on every page
(/usr/share/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def
File: l3backend-pdftex.def 2023-01-16 L3 backend support: PDF output (pdfTeX)
\l__color_backend_stack_int=\count197
\l__pdf_internal_box=\box53
)
\sc@wm@hcenter=\skip44
\sc@wm@vcenter=\skip45
\sc@wm@fontsize=\skip46
) (./kari_score.aux)
(./kari_score.aux)
\openout1 = `kari_score.aux'.
LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 22.
LaTeX Font Info: ... okay on input line 22.
LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 22.
LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 22.
LaTeX Font Info: ... okay on input line 22.
LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 22.
LaTeX Font Info: ... okay on input line 22.
LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 22.
LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 22.
LaTeX Font Info: ... okay on input line 22.
LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 22.
LaTeX Font Info: ... okay on input line 22.
LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 22.
LaTeX Font Info: ... okay on input line 22.
@ -221,69 +213,40 @@ LaTeX Font Info: ... okay on input line 22.
* \@reversemarginfalse
* (1in=72.27pt=25.4mm, 1cm=28.453pt)
\AtBeginShipoutBox=\box29
(/usr/share/texmf-dist/tex/context/base/mkii/supp-pdf.mkii
[Loading MPS to PDF converter (version 2006.09.02).]
\scratchcounter=\count90
\scratchdimen=\dimen118
\scratchbox=\box30
\nofMPsegments=\count91
\nofMParguments=\count92
\everyMPshowfont=\toks22
\MPscratchCnt=\count93
\MPscratchDim=\dimen119
\MPnumerator=\count94
\makeMPintoPDFobject=\count95
\everyMPtoPDFconversion=\toks23
) (/usr/share/texmf-dist/tex/latex/oberdiek/epstopdf-base.sty
Package: epstopdf-base 2016/05/15 v2.6 Base part for package epstopdf
(/usr/share/texmf-dist/tex/latex/oberdiek/grfext.sty
Package: grfext 2016/05/16 v1.2 Manage graphics extensions (HO)
(/usr/share/texmf-dist/tex/generic/oberdiek/kvdefinekeys.sty
Package: kvdefinekeys 2016/05/16 v1.4 Define keys (HO)
))
(/usr/share/texmf-dist/tex/latex/oberdiek/kvoptions.sty
Package: kvoptions 2016/05/16 v3.12 Key value format for package options (HO)
(/usr/share/texmf-dist/tex/generic/oberdiek/kvsetkeys.sty
Package: kvsetkeys 2016/05/16 v1.17 Key value parser (HO)
(/usr/share/texmf-dist/tex/generic/oberdiek/etexcmds.sty
Package: etexcmds 2016/05/16 v1.6 Avoid name clashes with e-TeX commands (HO)
(/usr/share/texmf-dist/tex/generic/oberdiek/ifluatex.sty
Package: ifluatex 2016/05/16 v1.4 Provides the ifluatex switch (HO)
Package ifluatex Info: LuaTeX not detected.
))))
(/usr/share/texmf-dist/tex/generic/oberdiek/pdftexcmds.sty
Package: pdftexcmds 2018/09/10 v0.29 Utility functions of pdfTeX for LuaTeX (HO
)
Package pdftexcmds Info: LuaTeX not detected.
Package pdftexcmds Info: \pdf@primitive is available.
Package pdftexcmds Info: \pdf@ifprimitive is available.
Package pdftexcmds Info: \pdfdraftmode found.
)
\scratchcounter=\count198
\scratchdimen=\dimen159
\scratchbox=\box54
\nofMPsegments=\count199
\nofMParguments=\count266
\everyMPshowfont=\toks25
\MPscratchCnt=\count267
\MPscratchDim=\dimen160
\MPnumerator=\count268
\makeMPintoPDFobject=\count269
\everyMPtoPDFconversion=\toks26
) (/usr/share/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty
Package: epstopdf-base 2020-01-24 v2.11 Base part for package epstopdf
Package epstopdf-base Info: Redefining graphics rule for `.eps' on input line 4
38.
Package grfext Info: Graphics extension search list:
(grfext) [.pdf,.png,.jpg,.mps,.jpeg,.jbig2,.jb2,.PDF,.PNG,.JPG,.JPE
G,.JBIG2,.JB2,.eps]
(grfext) \AppendGraphicsExtensions on input line 456.
85.
(/usr/share/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg
File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Liv
e
))
(/usr/share/texmf-dist/tex/latex/oberdiek/pdflscape.sty
Package: pdflscape 2016/05/14 v0.11 Display of landscape pages in PDF (HO)
(/usr/share/texmf-dist/tex/latex/pdflscape/pdflscape.sty
Package: pdflscape 2022-10-27 v0.13 Display of landscape pages in PDF
(/usr/share/texmf-dist/tex/latex/pdflscape/pdflscape-nometadata.sty
Package: pdflscape-nometadata 2022-10-28 v0.13 Display of landscape pages in PD
F (HO)
(/usr/share/texmf-dist/tex/latex/graphics/lscape.sty
Package: lscape 2000/10/22 v3.01 Landscape Pages (DPC)
Package: lscape 2020/05/28 v3.02 Landscape Pages (DPC)
)
Package pdflscape Info: Auto-detected driver: pdftex on input line 81.
)
))
<dynamic_curve.pdf, id=1, 782.925pt x 213.79875pt>
File: dynamic_curve.pdf Graphic file (type pdf)
<use dynamic_curve.pdf>
@ -313,12 +276,7 @@ File: ../../score/lilypond/kari_culik/kari_culik.pdf Graphic file (type pdf)
Package pdftex.def Info: ../../score/lilypond/kari_culik/kari_culik.pdf , page1
used on input line 64.
(pdftex.def) Requested size: 597.53821pt x 845.08372pt.
LaTeX Font Warning: Font shape `OT1/cmr/m/n' in size <142.26378> not available
(Font) size <24.88> substituted on input line 64.
[1
[1
{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map} <./dynamic_curve.pdf>]
File: ../../score/lilypond/kari_culik/kari_culik.pdf Graphic file (type pdf)
@ -336,8 +294,7 @@ File: ../../score/lilypond/kari_culik/kari_culik.pdf Graphic file (type pdf)
Package pdftex.def Info: ../../score/lilypond/kari_culik/kari_culik.pdf , page1
used on input line 64.
(pdftex.def) Requested size: 597.53821pt x 845.08372pt.
[2 <../../score/lilypond/kari_culik/kari_culik.pdf>]
[2 <../../score/lilypond/kari_culik/kari_culik.pdf>]
<../../score/lilypond/kari_culik/kari_culik.pdf, id=47, page=2, 597.51233pt x 8
45.0471pt>
File: ../../score/lilypond/kari_culik/kari_culik.pdf Graphic file (type pdf)
@ -391,7 +348,7 @@ File: ../../score/lilypond/kari_culik/kari_culik.pdf Graphic file (type pdf)
Package pdftex.def Info: ../../score/lilypond/kari_culik/kari_culik.pdf , page4
used on input line 64.
(pdftex.def) Requested size: 597.53821pt x 845.08372pt.
[5 <../../score/lilypond/kari_culik/kari_culik.pdf>]
[5 <../../score/lilypond/kari_culik/kari_culik.pdf>]
<../../score/lilypond/kari_culik/kari_culik.pdf, id=59, page=5, 597.51233pt x 8
45.0471pt>
File: ../../score/lilypond/kari_culik/kari_culik.pdf Graphic file (type pdf)
@ -445,7 +402,7 @@ File: ../../score/lilypond/kari_culik/kari_culik.pdf Graphic file (type pdf)
Package pdftex.def Info: ../../score/lilypond/kari_culik/kari_culik.pdf , page7
used on input line 64.
(pdftex.def) Requested size: 597.53821pt x 845.08372pt.
[8 <../../score/lilypond/kari_culik/kari_culik.pdf>]
[8 <../../score/lilypond/kari_culik/kari_culik.pdf>]
<../../score/lilypond/kari_culik/kari_culik.pdf, id=72, page=8, 597.51233pt x 8
45.0471pt>
File: ../../score/lilypond/kari_culik/kari_culik.pdf Graphic file (type pdf)
@ -589,31 +546,27 @@ File: ../../score/lilypond/kari_culik/kari_culik.pdf Graphic file (type pdf)
Package pdftex.def Info: ../../score/lilypond/kari_culik/kari_culik.pdf , page1
5 used on input line 64.
(pdftex.def) Requested size: 597.53821pt x 845.08372pt.
[16 <../../score/lilypond/kari_culik/kari_culik.pdf>] (./kari_score.aux)
LaTeX Font Warning: Size substitutions with differences
(Font) up to 117.38377pt have occurred.
)
[16 <../../score/lilypond/kari_culik/kari_culik.pdf>]
(./kari_score.aux) )
Here is how much of TeX's memory you used:
6216 strings out of 492623
112587 string characters out of 6135670
188854 words of memory out of 5000000
10050 multiletter control sequences out of 15000+600000
5940 words of font info for 21 fonts, out of 8000000 for 9000
1141 hyphenation exceptions out of 8191
41i,18n,51p,839b,514s stack positions out of 5000i,500n,10000p,200000b,80000s
</usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmbxti10.pfb></usr/shar
e/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb></usr/share/texmf-dist/fo
nts/type1/public/amsfonts/cm/cmr8.pfb></usr/share/texmf-dist/fonts/type1/public
/amsfonts/cm/cmti10.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/c
mti8.pfb></usr/share/texmf-dist/fonts/type1/public/tex-gyre/qcsb.pfb></usr/shar
e/texmf-dist/fonts/type1/public/tex-gyre/qcsbi.pfb></usr/share/texmf-dist/fonts
/type1/public/tex-gyre/qcsr.pfb></usr/share/texmf-dist/fonts/type1/public/tex-g
yre/qcsri.pfb>
Output written on kari_score.pdf (16 pages, 367843 bytes).
6390 strings out of 477985
124081 string characters out of 5840059
1857388 words of memory out of 5000000
26543 multiletter control sequences out of 15000+600000
514288 words of font info for 38 fonts, out of 8000000 for 9000
14 hyphenation exceptions out of 8191
72i,17n,76p,752b,518s stack positions out of 10000i,1000n,20000p,200000b,200000s
</usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmbxt
i10.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb></usr/s
hare/texmf-dist/fonts/type1/public/amsfonts/cm/cmr8.pfb></usr/share/texmf-dist/
fonts/type1/public/amsfonts/cm/cmti10.pfb></usr/share/texmf-dist/fonts/type1/pu
blic/amsfonts/cm/cmti8.pfb></usr/share/texmf-dist/fonts/type1/public/tex-gyre/q
csb.pfb></usr/share/texmf-dist/fonts/type1/public/tex-gyre/qcsbi.pfb></usr/shar
e/texmf-dist/fonts/type1/public/tex-gyre/qcsr.pfb></usr/share/texmf-dist/fonts/
type1/public/tex-gyre/qcsri.pfb>
Output written on kari_score.pdf (16 pages, 371160 bytes).
PDF statistics:
127 PDF objects out of 1000 (max. 8388607)
132 PDF objects out of 1000 (max. 8388607)
78 compressed objects within 1 object stream
0 named destinations out of 1000 (max. 500000)
96 words of extra memory for PDF output out of 10000 (max. 10000000)

Binary file not shown.

@ -6,18 +6,18 @@
\usepackage{verbatim}
\usepackage{pdfpages}
\usepackage{datetime2}
\usepackage{draftwatermark}
%\usepackage{draftwatermark}
\usepackage{graphicx}
\DTMsetdatestyle{default}
\DTMsetup{datesep={.}}
\SetWatermarkColor[rgb]{1, 0.6, 0.6}
\SetWatermarkScale{2}
\SetWatermarkHorCenter{4in}
\SetWatermarkVerCenter{4in}
\SetWatermarkText{UNFINISHED DRAFT}
\SetWatermarkText{}
%\SetWatermarkColor[rgb]{1, 0.6, 0.6}
%\SetWatermarkScale{2}
%\SetWatermarkHorCenter{4in}
%\SetWatermarkVerCenter{4in}
%\SetWatermarkText{UNFINISHED DRAFT}
%\SetWatermarkText{}
\begin{document}
\thispagestyle{empty}
@ -32,7 +32,7 @@ for sustaining instruments and noise / percussion
\bigskip
\normalsize
The piece consists of a set of `ensemble' instruments notated in the top staff group along with a bass part and a noise / percussion part notated in the bottom staff group. At least 3 of the ensemble parts should be performed (but preferably all). Each of the the ensemble parts span several octaves. To the extent possible, each pitch should be played in the written register. If a single instrument cannot cover the entire range, the part may be played by two instruments. Another option is to transpose or omit notes that are out of range while maintaining a generally open registral spacing and ensuring that the piece does not feel too sparse / empty. Each ensemble part should be as distinct in timbre as possible.
The piece consists of a set of `ensemble' instruments notated in the top staff group along with a bass part and a noise / percussion part notated in the bottom staff group. At least 3 of the ensemble parts should be performed (but preferably all). Each of the ensemble parts span several octaves. To the extent possible, each pitch should be played in the written register. If a single instrument cannot cover the entire range, the part may be played by two instruments. Another option is to transpose or omit notes that are out of range while maintaining a generally open registral spacing and ensuring that the piece does not feel too sparse / empty. Each ensemble part should be as distinct in timbre as possible.
The ensemble can play any 4 or more adjacent sections. If the ensemble starts after the first section (the 2nd through 7th sections), the performers should ignore that the note is tied from a note in the previous measure (the last measure of the previous section). If ending before the final section (the 4th through 9th sections), the performers should ignore that the note is tied to a note in the following measure (the first measure of the following section).

@ -1,2 +1,3 @@
\relax
\catcode 95\active
\gdef \@abspage@last{31}

@ -1,186 +1,178 @@
This is pdfTeX, Version 3.14159265-2.6-1.40.20 (TeX Live 2019/Arch Linux) (preloaded format=pdflatex 2019.9.6) 6 DEC 2019 18:27
This is pdfTeX, Version 3.141592653-2.6-1.40.25 (TeX Live 2023/Arch Linux) (preloaded format=pdflatex 2023.7.4) 20 JUL 2023 18:32
entering extended mode
restricted \write18 enabled.
\write18 enabled.
%&-line parsing enabled.
**penrose_score.tex
(./penrose_score.tex
LaTeX2e <2018-12-01>
LaTeX2e <2022-11-01> patch level 1
L3 programming layer <2023-02-22>
(/usr/share/texmf-dist/tex/latex/base/letter.cls
Document Class: letter 2014/09/29 v1.2z Standard LaTeX document class
Document Class: letter 2021/12/07 v1.3c Standard LaTeX document class
(/usr/share/texmf-dist/tex/latex/base/size10.clo
File: size10.clo 2018/09/03 v1.4i Standard LaTeX file (size option)
File: size10.clo 2022/07/02 v1.4n Standard LaTeX file (size option)
)
\longindentation=\dimen102
\indentedwidth=\dimen103
\labelcount=\count80
\longindentation=\dimen140
\indentedwidth=\dimen141
\labelcount=\count185
)
(/usr/share/texmf-dist/tex/latex/geometry/geometry.sty
Package: geometry 2018/04/16 v5.8 Page Geometry
Package: geometry 2020/01/02 v5.9 Page Geometry
(/usr/share/texmf-dist/tex/latex/graphics/keyval.sty
Package: keyval 2014/10/28 v1.15 key=value parser (DPC)
\KV@toks@=\toks14
Package: keyval 2022/05/29 v1.15 key=value parser (DPC)
\KV@toks@=\toks16
)
(/usr/share/texmf-dist/tex/generic/oberdiek/ifpdf.sty
Package: ifpdf 2018/09/07 v3.3 Provides the ifpdf switch
)
(/usr/share/texmf-dist/tex/generic/oberdiek/ifvtex.sty
Package: ifvtex 2016/05/16 v1.6 Detect VTeX and its facilities (HO)
Package ifvtex Info: VTeX not detected.
)
(/usr/share/texmf-dist/tex/generic/ifxetex/ifxetex.sty
Package: ifxetex 2010/09/12 v0.6 Provides ifxetex conditional
)
\Gm@cnth=\count81
\Gm@cntv=\count82
\c@Gm@tempcnt=\count83
\Gm@bindingoffset=\dimen104
\Gm@wd@mp=\dimen105
\Gm@odd@mp=\dimen106
\Gm@even@mp=\dimen107
\Gm@layoutwidth=\dimen108
\Gm@layoutheight=\dimen109
\Gm@layouthoffset=\dimen110
\Gm@layoutvoffset=\dimen111
\Gm@dimlist=\toks15
(/usr/share/texmf-dist/tex/generic/iftex/ifvtex.sty
Package: ifvtex 2019/10/25 v1.7 ifvtex legacy package. Use iftex instead.
(/usr/share/texmf-dist/tex/generic/iftex/iftex.sty
Package: iftex 2022/02/03 v1.0f TeX engine tests
))
\Gm@cnth=\count186
\Gm@cntv=\count187
\c@Gm@tempcnt=\count188
\Gm@bindingoffset=\dimen142
\Gm@wd@mp=\dimen143
\Gm@odd@mp=\dimen144
\Gm@even@mp=\dimen145
\Gm@layoutwidth=\dimen146
\Gm@layoutheight=\dimen147
\Gm@layouthoffset=\dimen148
\Gm@layoutvoffset=\dimen149
\Gm@dimlist=\toks17
)
(/usr/share/texmf-dist/tex/latex/underscore/underscore.sty
Package: underscore 2006/09/13
LaTeX Info: Redefining \_ on input line 42.
)
(/usr/share/texmf-dist/tex/latex/url/url.sty
\Urlmuskip=\muskip10
\Urlmuskip=\muskip16
Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc.
)
(/usr/share/texmf-dist/tex/latex/tools/verbatim.sty
Package: verbatim 2014/10/28 v1.5q LaTeX2e package for verbatim enhancements
\every@verbatim=\toks16
\verbatim@line=\toks17
\verbatim@in@stream=\read1
Package: verbatim 2022-07-02 v1.5u LaTeX2e package for verbatim enhancements
\every@verbatim=\toks18
\verbatim@line=\toks19
\verbatim@in@stream=\read2
)
(/usr/share/texmf-dist/tex/latex/pdfpages/pdfpages.sty
Package: pdfpages 2017/10/31 v0.5l Insert pages of external PDF documents (AM)
Package: pdfpages 2022/12/19 v0.5x Insert pages of external PDF documents (AM)
(/usr/share/texmf-dist/tex/latex/base/ifthen.sty
Package: ifthen 2014/09/29 v1.1c Standard LaTeX ifthen package (DPC)
Package: ifthen 2022/04/13 v1.1d Standard LaTeX ifthen package (DPC)
)
(/usr/share/texmf-dist/tex/latex/tools/calc.sty
Package: calc 2017/05/25 v4.3 Infix arithmetic (KKT,FJ)
\calc@Acount=\count84
\calc@Bcount=\count85
\calc@Adimen=\dimen112
\calc@Bdimen=\dimen113
\calc@Askip=\skip41
\calc@Bskip=\skip42
\calc@Acount=\count189
\calc@Bcount=\count190
\calc@Adimen=\dimen150
\calc@Bdimen=\dimen151
\calc@Askip=\skip48
\calc@Bskip=\skip49
LaTeX Info: Redefining \setlength on input line 80.
LaTeX Info: Redefining \addtolength on input line 81.
\calc@Ccount=\count86
\calc@Cskip=\skip43
\calc@Ccount=\count191
\calc@Cskip=\skip50
)
(/usr/share/texmf-dist/tex/latex/eso-pic/eso-pic.sty
Package: eso-pic 2018/04/12 v2.0h eso-pic (RN)
Package: eso-pic 2020/10/14 v3.0a eso-pic (RN)
\ESO@tempdima=\dimen152
\ESO@tempdimb=\dimen153
(/usr/share/texmf-dist/tex/generic/oberdiek/atbegshi.sty
Package: atbegshi 2016/06/09 v1.18 At begin shipout hook (HO)
(/usr/share/texmf-dist/tex/generic/oberdiek/infwarerr.sty
Package: infwarerr 2016/05/16 v1.4 Providing info/warning/error messages (HO)
)
(/usr/share/texmf-dist/tex/generic/oberdiek/ltxcmds.sty
Package: ltxcmds 2016/05/16 v1.23 LaTeX kernel commands for general use (HO)
))
(/usr/share/texmf-dist/tex/latex/xcolor/xcolor.sty
Package: xcolor 2016/05/11 v2.12 LaTeX color extensions (UK)
Package: xcolor 2022/06/12 v2.14 LaTeX color extensions (UK)
(/usr/share/texmf-dist/tex/latex/graphics-cfg/color.cfg
File: color.cfg 2016/01/02 v1.6 sample color configuration
)
Package xcolor Info: Driver file: pdftex.def on input line 225.
Package xcolor Info: Driver file: pdftex.def on input line 227.
(/usr/share/texmf-dist/tex/latex/graphics-def/pdftex.def
File: pdftex.def 2018/01/08 v1.0l Graphics/color driver for pdftex
File: pdftex.def 2022/09/22 v1.2b Graphics/color driver for pdftex
)
Package xcolor Info: Model `cmy' substituted by `cmy0' on input line 1348.
Package xcolor Info: Model `hsb' substituted by `rgb' on input line 1352.
Package xcolor Info: Model `RGB' extended on input line 1364.
Package xcolor Info: Model `HTML' substituted by `rgb' on input line 1366.
Package xcolor Info: Model `Hsb' substituted by `hsb' on input line 1367.
Package xcolor Info: Model `tHsb' substituted by `hsb' on input line 1368.
Package xcolor Info: Model `HSB' substituted by `hsb' on input line 1369.
Package xcolor Info: Model `Gray' substituted by `gray' on input line 1370.
Package xcolor Info: Model `wave' substituted by `hsb' on input line 1371.
(/usr/share/texmf-dist/tex/latex/graphics/mathcolor.ltx)
Package xcolor Info: Model `cmy' substituted by `cmy0' on input line 1353.
Package xcolor Info: Model `hsb' substituted by `rgb' on input line 1357.
Package xcolor Info: Model `RGB' extended on input line 1369.
Package xcolor Info: Model `HTML' substituted by `rgb' on input line 1371.
Package xcolor Info: Model `Hsb' substituted by `hsb' on input line 1372.
Package xcolor Info: Model `tHsb' substituted by `hsb' on input line 1373.
Package xcolor Info: Model `HSB' substituted by `hsb' on input line 1374.
Package xcolor Info: Model `Gray' substituted by `gray' on input line 1375.
Package xcolor Info: Model `wave' substituted by `hsb' on input line 1376.
))
(/usr/share/texmf-dist/tex/latex/graphics/graphicx.sty
Package: graphicx 2017/06/01 v1.1a Enhanced LaTeX Graphics (DPC,SPQR)
Package: graphicx 2021/09/16 v1.2d Enhanced LaTeX Graphics (DPC,SPQR)
(/usr/share/texmf-dist/tex/latex/graphics/graphics.sty
Package: graphics 2017/06/25 v1.2c Standard LaTeX Graphics (DPC,SPQR)
Package: graphics 2022/03/10 v1.4e Standard LaTeX Graphics (DPC,SPQR)
(/usr/share/texmf-dist/tex/latex/graphics/trig.sty
Package: trig 2016/01/03 v1.10 sin cos tan (DPC)
Package: trig 2021/08/11 v1.11 sin cos tan (DPC)
)
(/usr/share/texmf-dist/tex/latex/graphics-cfg/graphics.cfg
File: graphics.cfg 2016/06/04 v1.11 sample graphics configuration
)
Package graphics Info: Driver file: pdftex.def on input line 99.
Package graphics Info: Driver file: pdftex.def on input line 107.
)
\Gin@req@height=\dimen114
\Gin@req@width=\dimen115
\Gin@req@height=\dimen154
\Gin@req@width=\dimen155
)
\AM@pagewidth=\dimen116
\AM@pageheight=\dimen117
\AM@pagewidth=\dimen156
\AM@pageheight=\dimen157
\AM@fboxrule=\dimen158
(/usr/share/texmf-dist/tex/latex/pdfpages/pppdftex.def
File: pppdftex.def 2017/10/31 v0.5l Pdfpages driver for pdfTeX (AM)
File: pppdftex.def 2022/12/19 v0.5x Pdfpages driver for pdfTeX (AM)
)
\AM@pagebox=\box27
\AM@global@opts=\toks18
\AM@toc@title=\toks19
\c@AM@survey=\count87
\AM@templatesizebox=\box28
\pdfpages@includegraphics@status=\count192
\AM@pagebox=\box51
\AM@global@opts=\toks20
\AM@pagecnt=\count193
\AM@toc@title=\toks21
\AM@lof@heading=\toks22
\c@AM@survey=\count194
\AM@templatesizebox=\box52
)
(/usr/share/texmf-dist/tex/latex/datetime2/datetime2.sty
Package: datetime2 2018/07/20 v1.5.3 (NLCT) date and time formats
Package: datetime2 2021/03/21 v1.5.7 (NLCT) date and time formats
(/usr/share/texmf-dist/tex/latex/tracklang/tracklang.sty
Package: tracklang 2018/05/13 v1.3.6 (NLCT) Track Languages
Package: tracklang 2022/12/13 v1.6.1 (NLCT) Track Languages
(/usr/share/texmf-dist/tex/generic/tracklang/tracklang.tex))
(/usr/share/texmf-dist/tex/latex/etoolbox/etoolbox.sty
Package: etoolbox 2018/08/19 v2.5f e-TeX tools for LaTeX (JAW)
\etb@tempcnta=\count88
Package: etoolbox 2020/10/05 v2.5k e-TeX tools for LaTeX (JAW)
\etb@tempcnta=\count195
)
(/usr/share/texmf-dist/tex/latex/xkeyval/xkeyval.sty
Package: xkeyval 2014/12/03 v2.7a package option processing (HA)
Package: xkeyval 2022/06/16 v2.9 package option processing (HA)
(/usr/share/texmf-dist/tex/generic/xkeyval/xkeyval.tex
(/usr/share/texmf-dist/tex/generic/xkeyval/xkvutils.tex
\XKV@toks=\toks20
\XKV@tempa@toks=\toks21
\XKV@toks=\toks23
\XKV@tempa@toks=\toks24
)
\XKV@depth=\count89
\XKV@depth=\count196
File: xkeyval.tex 2014/12/03 v2.7a key=value parser (HA)
)))
(/usr/share/texmf-dist/tex/latex/draftwatermark/draftwatermark.sty
Package: draftwatermark 2015/02/19 1.2 Put a gray textual watermark on document
pages
(/usr/share/texmf-dist/tex/latex/everypage/everypage.sty
Package: everypage 2007/06/20 1.1 Hooks to run on every page
(/usr/share/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def
File: l3backend-pdftex.def 2023-01-16 L3 backend support: PDF output (pdfTeX)
\l__color_backend_stack_int=\count197
\l__pdf_internal_box=\box53
)
\sc@wm@hcenter=\skip44
\sc@wm@vcenter=\skip45
\sc@wm@fontsize=\skip46
) (./penrose_score.aux)
(./penrose_score.aux)
\openout1 = `penrose_score.aux'.
LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 22.
LaTeX Font Info: ... okay on input line 22.
LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 22.
LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 22.
LaTeX Font Info: ... okay on input line 22.
LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 22.
LaTeX Font Info: ... okay on input line 22.
LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 22.
LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 22.
LaTeX Font Info: ... okay on input line 22.
LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 22.
LaTeX Font Info: ... okay on input line 22.
LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 22.
LaTeX Font Info: ... okay on input line 22.
@ -221,69 +213,40 @@ LaTeX Font Info: ... okay on input line 22.
* \@reversemarginfalse
* (1in=72.27pt=25.4mm, 1cm=28.453pt)
\AtBeginShipoutBox=\box29
(/usr/share/texmf-dist/tex/context/base/mkii/supp-pdf.mkii
[Loading MPS to PDF converter (version 2006.09.02).]
\scratchcounter=\count90
\scratchdimen=\dimen118
\scratchbox=\box30
\nofMPsegments=\count91
\nofMParguments=\count92
\everyMPshowfont=\toks22
\MPscratchCnt=\count93
\MPscratchDim=\dimen119
\MPnumerator=\count94
\makeMPintoPDFobject=\count95
\everyMPtoPDFconversion=\toks23
) (/usr/share/texmf-dist/tex/latex/oberdiek/epstopdf-base.sty
Package: epstopdf-base 2016/05/15 v2.6 Base part for package epstopdf
(/usr/share/texmf-dist/tex/latex/oberdiek/grfext.sty
Package: grfext 2016/05/16 v1.2 Manage graphics extensions (HO)
(/usr/share/texmf-dist/tex/generic/oberdiek/kvdefinekeys.sty
Package: kvdefinekeys 2016/05/16 v1.4 Define keys (HO)
))
(/usr/share/texmf-dist/tex/latex/oberdiek/kvoptions.sty
Package: kvoptions 2016/05/16 v3.12 Key value format for package options (HO)
(/usr/share/texmf-dist/tex/generic/oberdiek/kvsetkeys.sty
Package: kvsetkeys 2016/05/16 v1.17 Key value parser (HO)
(/usr/share/texmf-dist/tex/generic/oberdiek/etexcmds.sty
Package: etexcmds 2016/05/16 v1.6 Avoid name clashes with e-TeX commands (HO)
(/usr/share/texmf-dist/tex/generic/oberdiek/ifluatex.sty
Package: ifluatex 2016/05/16 v1.4 Provides the ifluatex switch (HO)
Package ifluatex Info: LuaTeX not detected.
))))
(/usr/share/texmf-dist/tex/generic/oberdiek/pdftexcmds.sty
Package: pdftexcmds 2018/09/10 v0.29 Utility functions of pdfTeX for LuaTeX (HO
)
Package pdftexcmds Info: LuaTeX not detected.
Package pdftexcmds Info: \pdf@primitive is available.
Package pdftexcmds Info: \pdf@ifprimitive is available.
Package pdftexcmds Info: \pdfdraftmode found.
)
\scratchcounter=\count198
\scratchdimen=\dimen159
\scratchbox=\box54
\nofMPsegments=\count199
\nofMParguments=\count266
\everyMPshowfont=\toks25
\MPscratchCnt=\count267
\MPscratchDim=\dimen160
\MPnumerator=\count268
\makeMPintoPDFobject=\count269
\everyMPtoPDFconversion=\toks26
) (/usr/share/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty
Package: epstopdf-base 2020-01-24 v2.11 Base part for package epstopdf
Package epstopdf-base Info: Redefining graphics rule for `.eps' on input line 4
38.
Package grfext Info: Graphics extension search list:
(grfext) [.pdf,.png,.jpg,.mps,.jpeg,.jbig2,.jb2,.PDF,.PNG,.JPG,.JPE
G,.JBIG2,.JB2,.eps]
(grfext) \AppendGraphicsExtensions on input line 456.
85.
(/usr/share/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg
File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Liv
e
))
(/usr/share/texmf-dist/tex/latex/oberdiek/pdflscape.sty
Package: pdflscape 2016/05/14 v0.11 Display of landscape pages in PDF (HO)
(/usr/share/texmf-dist/tex/latex/pdflscape/pdflscape.sty
Package: pdflscape 2022-10-27 v0.13 Display of landscape pages in PDF
(/usr/share/texmf-dist/tex/latex/pdflscape/pdflscape-nometadata.sty
Package: pdflscape-nometadata 2022-10-28 v0.13 Display of landscape pages in PD
F (HO)
(/usr/share/texmf-dist/tex/latex/graphics/lscape.sty
Package: lscape 2000/10/22 v3.01 Landscape Pages (DPC)
Package: lscape 2020/05/28 v3.02 Landscape Pages (DPC)
)
Package pdflscape Info: Auto-detected driver: pdftex on input line 81.
)
))
<penrose_pitches.pdf, id=1, 578.16pt x 54.2025pt>
File: penrose_pitches.pdf Graphic file (type pdf)
<use penrose_pitches.pdf>
@ -312,12 +275,7 @@ File: ../../score/lilypond/penrose/penrose.pdf Graphic file (type pdf)
Package pdftex.def Info: ../../score/lilypond/penrose/penrose.pdf , page1 used
on input line 59.
(pdftex.def) Requested size: 597.53821pt x 845.08372pt.
LaTeX Font Warning: Font shape `OT1/cmr/m/n' in size <142.26378> not available
(Font) size <24.88> substituted on input line 59.
[1
[1
{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map} <./penrose_pitches.pdf>]
File: ../../score/lilypond/penrose/penrose.pdf Graphic file (type pdf)
@ -335,8 +293,7 @@ File: ../../score/lilypond/penrose/penrose.pdf Graphic file (type pdf)
Package pdftex.def Info: ../../score/lilypond/penrose/penrose.pdf , page1 used
on input line 59.
(pdftex.def) Requested size: 597.53821pt x 845.08372pt.
[2 <../../score/lilypond/penrose/penrose.pdf>]
[2 <../../score/lilypond/penrose/penrose.pdf>]
<../../score/lilypond/penrose/penrose.pdf, id=52, page=2, 597.51233pt x 845.047
1pt>
File: ../../score/lilypond/penrose/penrose.pdf Graphic file (type pdf)
@ -426,8 +383,7 @@ File: ../../score/lilypond/penrose/penrose.pdf Graphic file (type pdf)
Package pdftex.def Info: ../../score/lilypond/penrose/penrose.pdf , page6 used
on input line 59.
(pdftex.def) Requested size: 597.53821pt x 845.08372pt.
[7 <../../score/lilypond/penrose/penrose.pdf>]
[7 <../../score/lilypond/penrose/penrose.pdf>]
<../../score/lilypond/penrose/penrose.pdf, id=73, page=7, 597.51233pt x 845.047
1pt>
File: ../../score/lilypond/penrose/penrose.pdf Graphic file (type pdf)
@ -517,8 +473,7 @@ File: ../../score/lilypond/penrose/penrose.pdf Graphic file (type pdf)
Package pdftex.def Info: ../../score/lilypond/penrose/penrose.pdf , page11 used
on input line 59.
(pdftex.def) Requested size: 597.53821pt x 845.08372pt.
[12 <../../score/lilypond/penrose/penrose.pdf>]
[12 <../../score/lilypond/penrose/penrose.pdf>]
<../../score/lilypond/penrose/penrose.pdf, id=93, page=12, 597.51233pt x 845.04
71pt>
File: ../../score/lilypond/penrose/penrose.pdf Graphic file (type pdf)
@ -644,7 +599,8 @@ File: ../../score/lilypond/penrose/penrose.pdf Graphic file (type pdf)
Package pdftex.def Info: ../../score/lilypond/penrose/penrose.pdf , page18 used
on input line 59.
(pdftex.def) Requested size: 597.53821pt x 845.08372pt.
[19 <../../score/lilypond/penrose/penrose.pdf>]
[19 <../../score/lilypond/penrose/penrose.pdf>]
<../../score/lilypond/penrose/penrose.pdf, id=123, page=19, 597.51233pt x 845.0
471pt>
File: ../../score/lilypond/penrose/penrose.pdf Graphic file (type pdf)
@ -842,8 +798,7 @@ File: ../../score/lilypond/penrose/penrose.pdf Graphic file (type pdf)
Package pdftex.def Info: ../../score/lilypond/penrose/penrose.pdf , page29 used
on input line 59.
(pdftex.def) Requested size: 597.53821pt x 845.08372pt.
[30 <../../score/lilypond/penrose/penrose.pdf>]
[30 <../../score/lilypond/penrose/penrose.pdf>]
<../../score/lilypond/penrose/penrose.pdf, id=168, page=30, 597.51233pt x 845.0
471pt>
File: ../../score/lilypond/penrose/penrose.pdf Graphic file (type pdf)
@ -861,31 +816,27 @@ File: ../../score/lilypond/penrose/penrose.pdf Graphic file (type pdf)
Package pdftex.def Info: ../../score/lilypond/penrose/penrose.pdf , page30 used
on input line 59.
(pdftex.def) Requested size: 597.53821pt x 845.08372pt.
[31 <../../score/lilypond/penrose/penrose.pdf>] (./penrose_score.aux)
LaTeX Font Warning: Size substitutions with differences
(Font) up to 117.38377pt have occurred.
)
[31 <../../score/lilypond/penrose/penrose.pdf>]
(./penrose_score.aux) )
Here is how much of TeX's memory you used:
6261 strings out of 492623
114946 string characters out of 6135670
187854 words of memory out of 5000000
10095 multiletter control sequences out of 15000+600000
5940 words of font info for 21 fonts, out of 8000000 for 9000
1141 hyphenation exceptions out of 8191
41i,18n,51p,842b,514s stack positions out of 5000i,500n,10000p,200000b,80000s
</usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmbxti10.pfb></usr/shar
e/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb></usr/share/texmf-dist/fo
nts/type1/public/amsfonts/cm/cmr8.pfb></usr/share/texmf-dist/fonts/type1/public
/amsfonts/cm/cmti10.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/c
mti8.pfb></usr/share/texmf-dist/fonts/type1/public/tex-gyre/qcsb.pfb></usr/shar
e/texmf-dist/fonts/type1/public/tex-gyre/qcsbi.pfb></usr/share/texmf-dist/fonts
/type1/public/tex-gyre/qcsr.pfb></usr/share/texmf-dist/fonts/type1/public/tex-g
yre/qcsri.pfb>
Output written on penrose_score.pdf (31 pages, 1137754 bytes).
6435 strings out of 477985
126426 string characters out of 5840059
1854388 words of memory out of 5000000
26588 multiletter control sequences out of 15000+600000
514288 words of font info for 38 fonts, out of 8000000 for 9000
14 hyphenation exceptions out of 8191
72i,17n,76p,647b,518s stack positions out of 10000i,1000n,20000p,200000b,200000s
</usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cm
bxti10.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb></us
r/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmr8.pfb></usr/share/texmf-di
st/fonts/type1/public/amsfonts/cm/cmti10.pfb></usr/share/texmf-dist/fonts/type1
/public/amsfonts/cm/cmti8.pfb></usr/share/texmf-dist/fonts/type1/public/tex-gyr
e/qcsb.pfb></usr/share/texmf-dist/fonts/type1/public/tex-gyre/qcsbi.pfb></usr/s
hare/texmf-dist/fonts/type1/public/tex-gyre/qcsr.pfb></usr/share/texmf-dist/fon
ts/type1/public/tex-gyre/qcsri.pfb>
Output written on penrose_score.pdf (31 pages, 1140680 bytes).
PDF statistics:
196 PDF objects out of 1000 (max. 8388607)
201 PDF objects out of 1000 (max. 8388607)
115 compressed objects within 2 object streams
0 named destinations out of 1000 (max. 500000)
171 words of extra memory for PDF output out of 10000 (max. 10000000)

@ -6,18 +6,18 @@
\usepackage{verbatim}
\usepackage{pdfpages}
\usepackage{datetime2}
\usepackage{draftwatermark}
%\usepackage{draftwatermark}
\usepackage{graphicx}
\DTMsetdatestyle{default}
\DTMsetup{datesep={.}}
\SetWatermarkColor[rgb]{1, 0.6, 0.6}
\SetWatermarkScale{2}
\SetWatermarkHorCenter{4in}
\SetWatermarkVerCenter{4in}
\SetWatermarkText{UNFINISHED DRAFT}
\SetWatermarkText{}
%\SetWatermarkColor[rgb]{1, 0.6, 0.6}
%\SetWatermarkScale{2}
%\SetWatermarkHorCenter{4in}
%\SetWatermarkVerCenter{4in}
%\SetWatermarkText{UNFINISHED DRAFT}
%\SetWatermarkText{}
\begin{document}
\thispagestyle{empty}
@ -32,7 +32,7 @@ for 4 to 6 sustaining instruments
\bigskip
\normalsize
The ensemble can play any 4 or more parts (preferably as many as possible) and any 8 or more adjacent sections. The ensemble can explore replacing pitches of the one of the outer parts with various non-pitched percussion instruments with relatively long decays.
The ensemble can play any 4 or more parts (preferably as many as possible) and any 8 or more adjacent sections. The ensemble can explore replacing pitches of one of the outer parts with various non-pitched percussion instruments with relatively long decays.
The piece should feel rather tranquil with a relatively constant dynamic throughout the piece. Parts with a higher temporal density at any given point should rise slightly above the rest of the ensemble. This sense of phrasing should come out naturally based on the temporal density alone, but can be further articulated by the performers applying a subtle swell over sequences of notes with relatively shorter durations. As a result, each section should be heard as a series of undulations / breaths. Performers may also occasionally omit or cut short a note in order to breathe or give a sense of phrasing.

@ -66,7 +66,7 @@ s.waitForBoot({
b = 6.collect({var buf = Buffer.alloc(s, 512, 1); buf.sine1(1.0 / 5.collect({arg i; pow(i + 1, 5.0.rand + 1)}), true, true, true)});
SynthDef(\ammann, {arg freq, amp, del = 5, gate = 1, sustain = 1, buf = 0, out = 0;
Out.ar(out, Osc.ar(Select.kr(buf, b), freq, 0, amp) * EnvGen.kr(Env.adsr(0.05, sustain, 0.5, 0.1), gate, 1, 0, 1, doneAction: 2));
Out.ar(out, Osc.ar(Select.kr(buf, b), freq, 0, amp) * EnvGen.kr(Env.adsr(3, sustain - 4, 1, 1), gate, 1, 0, 1, doneAction: 2));
}).add;
};
@ -172,7 +172,8 @@ s.waitForBoot({
\buf, i,
\out, hdpBusArray[i],
//\freq, Pseq((55 * r.slice(nil, 2).flatten).cpsmidi.round(0.5).midicps),
\freq, Pseq((55 * r.slice(nil, 2).flatten)),
//\freq, Pseq((55 * r.slice(nil, 2).flatten)) / 8 * pow(2, i),
\freq, Pseq(r.slice(nil, 2).flatten.collect({arg harm; (55 * harm) / 4 * pow(2, i) * pow(2, if(harm < 8, {0}, {0}))})),
\dur, Pseq(r.slice(nil, 0).flat),
//this is a bit tricky it makes it so that each note goes to the next
@ -350,9 +351,9 @@ s.waitForBoot({
OSCdef(\mixer, {arg msg, time, addr, port;
[msg, time, addr, port].postln;
if(msg[1] != "volume_master", {
mixer.set((msg[1] ++ '_' ++ msg[2]), msg[3])
[msg, time, addr, port];
if(msg[1].asString != "volume_master", {
mixer.set((msg[1] ++ '_' ++ msg[2]), msg[3]);
}, {
mixer.set(msg[1], msg[2])
});

@ -1,149 +0,0 @@
# importing libraries
import cv2
import numpy as np
from scipy import stats
drawing = False
point1 = ()
point2 = ()
def mouse_drawing(event, x, y, flags, params):
global point1, point2, drawing
if event == cv2.EVENT_LBUTTONDOWN:
if drawing is False:
drawing = True
point1 = (x, y)
else:
drawing = False
elif event == cv2.EVENT_MOUSEMOVE:
if drawing is True:
point2 = (x, y)
# Our ROI, defined by two points
p1, p2 = None, None
state = 0
# Called every time a mouse event happen
def on_mouse(event, x, y, flags, userdata):
global state, point1, point2
# Left click
if event == cv2.EVENT_LBUTTONUP:
# Select first point
if state == 0:
point1 = (x,y)
state += 1
# Select second point
elif state == 1:
point2 = (x,y)
state += 1
#xFine = (848, 187, 225, 21.0)
#yFine = (604, 402, 20.5, 276)
xFine = (848, 187, 848 + 225, 187 + 21.0)
yFine = (604, 402, 604 + 20.5, 402 + 276)
frameCountMod = 0
centroidX = [0, 0]
centroidY = [0, 0]
def track(frame, ROI, centroid, update):
if(update):
crop = frame[int(ROI[1]):int(ROI[3]), int(ROI[0]):int(ROI[2])]
crop = cv2.cvtColor(crop, cv2.COLOR_RGB2GRAY)
crop = cv2.GaussianBlur(crop,(7,7),cv2.BORDER_DEFAULT)
#ret, thresh = cv2.threshold(crop, 100, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY)
ret,thresh = cv2.threshold(crop, 50, 255, 0)
M = cv2.moments(thresh)
# calculate x,y coordinate of center
if M["m00"] != 0:
centroid[0] = int(M["m10"] / M["m00"])
centroid[1] = int(M["m01"] / M["m00"])
#else:
# cX, cY = 0, 0
#print(cY)
cv2.circle(frame, (int(ROI[0]) + centroid[0], int(ROI[1]) + centroid[1]), 3, (0, 255, 0), -1)
cv2.namedWindow("Frame")
cv2.setMouseCallback("Frame", mouse_drawing)
cv2.namedWindow("Process")
# Create a VideoCapture object and read from input file
cap = cv2.VideoCapture("/home/mwinter/Portfolio/a_history_of_the_domino_problem/a_history_of_the_domino_problem_source/recs/a_history_of_the_domino_problem_final_documentation_hq.mp4")
cap.set(cv2.CAP_PROP_POS_FRAMES, 10000)
# Check if camera opened successfully
if (cap.isOpened()== False):
print("Error opening video file")
frameCountMod = 0
centroidX = [0, 0]
centroidY = [0, 0]
# Read until video is completed
while(cap.isOpened()):
# Capture frame-by-frame
ret, frame = cap.read()
if ret == True:
# Display the resulting frame
if point1 and point2:
px = sorted([point1[0], point2[0]])
py = sorted([point1[1], point2[1]])
#cv2.rectangle(frame, point1, point2, (0, 255, 0))
xFine = (px[0], py[0], px[1], py[1])
crop = frame[int(xFine[1]):int(xFine[3]), int(xFine[0]):int(xFine[2])]
gray = cv2.cvtColor(crop, cv2.COLOR_BGR2GRAY)
fm = cv2.Laplacian(gray, cv2.CV_64F).var()
kernel = np.ones((30, 50), np.uint8)
text = "Not Blurry"
blur = cv2.GaussianBlur(cv2.bitwise_not(crop),(1001,3), 3, 1) * 3
dilation = cv2.dilate(gray, kernel, iterations=1)
ret,dilation = cv2.threshold(dilation,20,255,cv2.THRESH_BINARY_INV)
mean = pow(dilation.mean(), 3)
# if the focus measure is less than the supplied threshold,
# then the image should be considered "blurry"
if fm < 100.0:
text = "Blurry"
# show the image
cv2.rectangle(frame, (int(xFine[0]), int(xFine[1])), (int(xFine[2]),int(xFine[3])), (0, 255, 0))
cv2.rectangle(frame, (int(xFine[0]), int(xFine[1])), (int(xFine[2]),int(xFine[3])), (0, 255, 0))
cv2.putText(frame, "{}: {:.2f}".format(text, fm), (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3)
cv2.putText(frame, "{}: {:.2f}".format("Brightness", mean), (10, 100),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3)
cv2.imshow("Frame", frame)
cv2.imshow("Process", crop)
# Press Q on keyboard to exit
key = cv2.waitKey(100)
if key == 32:
cv2.waitKey()
elif key == ord('q'):
break
# Break the loop
else:
break
# When everything done, release
# the video capture object
cap.release()
# Closes all the frames
cv2.destroyAllWindows()

@ -1,148 +0,0 @@
# importing libraries
import cv2
import numpy as np
from scipy import stats
rectToSet = 'x'
moving = False
roiXCenter = (960, 195)
roiYCenter = (615, 530)
w = 10
l1 = 50
l2 = 150
l3 = 20
roiXInner = (roiXCenter[0] - l1, roiXCenter[1] - w, roiXCenter[0] + l1, roiXCenter[1] + w)
roiXOuter = (roiXCenter[0] - l2, roiXCenter[1] - w, roiXCenter[0] + l2, roiXCenter[1] + w)
roiXCourse = (roiXCenter[0] - l3, roiXCenter[1] + (w * 1), roiXCenter[0] + l3, roiXCenter[1] + (w * 3))
roiYInner = (roiYCenter[0] - w, roiYCenter[1] - l1, roiYCenter[0] + w, roiYCenter[1] + l1)
roiYOuter = (roiYCenter[0] - w, roiYCenter[1] - l2, roiYCenter[0] + w, roiYCenter[1] + l2)
roiYCourse = (roiYCenter[0] + (w * 1), roiYCenter[1] - l3, roiYCenter[0] + (w * 3), roiYCenter[1] + l3)
dilationVal = 75
def moveROI(event, x, y, flags, params):
global roiXCenter, roiYCenter, roiXInner, roiXOuter, roiXCourse, roiYInner, roiYOuter, roiYCourse, moving
if event == cv2.EVENT_LBUTTONDOWN:
moving = True
elif event==cv2.EVENT_MOUSEMOVE:
if moving==True:
if rectToSet=='x':
roiXCenter = (x, y)
roiXInner = (roiXCenter[0] - l1, roiXCenter[1] - w, roiXCenter[0] + l1, roiXCenter[1] + w)
roiXOuter = (roiXCenter[0] - l2, roiXCenter[1] - w, roiXCenter[0] + l2, roiXCenter[1] + w)
roiXCourse = (roiXCenter[0] - l3, roiXCenter[1] + (w * 1), roiXCenter[0] + l3, roiXCenter[1] + (w * 3))
elif rectToSet=='y':
roiYCenter = (x, y)
roiYInner = (roiYCenter[0] - w, roiYCenter[1] - l1, roiYCenter[0] + w, roiYCenter[1] + l1)
roiYOuter = (roiYCenter[0] - w, roiYCenter[1] - l2, roiYCenter[0] + w, roiYCenter[1] + l2)
roiYCourse = (roiYCenter[0] + (w * 1), roiYCenter[1] - l3, roiYCenter[0] + (w * 3), roiYCenter[1] + l3)
elif event == cv2.EVENT_LBUTTONUP:
moving = False
cv2.namedWindow("Frame")
cv2.setMouseCallback("Frame", moveROI)
#cv2.namedWindow("Process")
# Create a VideoCapture object and read from input file
cap = cv2.VideoCapture("/home/mwinter/Portfolio/a_history_of_the_domino_problem/a_history_of_the_domino_problem_source/recs/a_history_of_the_domino_problem_final_documentation_hq.mp4")
cap.set(cv2.CAP_PROP_POS_FRAMES, 10000)
# Check if camera opened successfully
if (cap.isOpened()== False):
print("Error opening video file")
def track(frame, roiInner, roiOuter, roiCourse):
w = 30
l1 = 30
l2 = 100
cropFine = frame[roiOuter[1]:roiOuter[3], roiOuter[0]:roiOuter[2]]
cropCourse = frame[roiCourse[1]:roiCourse[3], roiCourse[0]:roiCourse[2]]
#gray = cv2.cvtColor(crop, cv2.COLOR_BGR2GRAY)
#may not need any of this
kernel = np.ones((dilationVal, dilationVal), np.uint8)
dilation = cv2.dilate(cropFine, kernel, iterations=1)
ret,tresh = cv2.threshold(dilation,20,255,cv2.THRESH_BINARY)
#mean = pow(frame[roiInner[1]:roiInner[3], roiInner[0]:roiInner[2]].mean(), 3)
frame[roiOuter[1]:roiOuter[3], roiOuter[0]:roiOuter[2]] = tresh
meanFine = pow(frame[roiInner[1]:roiInner[3], roiInner[0]:roiInner[2]].mean(), 2)
meanCourse = frame[roiCourse[1]:roiCourse[3], roiCourse[0]:roiCourse[2]].mean()
mean = 0
if(meanCourse > 10):
mean = meanFine
distance = pow(255, 2) - mean
return distance
def drawRects(frame):
cv2.rectangle(frame, (roiXOuter[0], roiXOuter[1]), (roiXOuter[2], roiXOuter[3]), (0, 255, 0))
cv2.rectangle(frame, (roiXCenter[0] - l1, roiXInner[1]), (roiXCenter[0], roiXInner[3]), (0, 255, 0))
cv2.rectangle(frame, (roiXCenter[0], roiXInner[1]), (roiXCenter[0] + l1, roiXInner[3]), (0, 255, 0))
cv2.rectangle(frame, (roiXCourse[0], roiXCourse[1]), (roiXCourse[2], roiXCourse[3]), (0, 255, 0))
cv2.rectangle(frame, (roiYOuter[0], roiYOuter[1]), (roiYOuter[2], roiYOuter[3]), (0, 255, 0))
cv2.rectangle(frame, (roiYInner[0], roiYCenter[1] - l1), (roiYInner[2], roiYCenter[1]), (0, 255, 0))
cv2.rectangle(frame, (roiYInner[0], roiYCenter[1]), (roiYInner[2], roiYCenter[1] + l1), (0, 255, 0))
cv2.rectangle(frame, (roiYCourse[0], roiYCourse[1]), (roiYCourse[2], roiYCourse[3]), (0, 255, 0))
# Read until video is completed
while(cap.isOpened()):
# Capture frame-by-frame
ret, frame = cap.read()
if ret == True:
# Display the resulting frame
distanceX = track(frame, roiXInner, roiXOuter, roiXCourse)
distanceY = track(frame, roiYInner, roiYOuter, roiYCourse)
drawRects(frame)
cv2.putText(frame, "{}: {:.2f}".format("distance x", distanceX), (10, 100), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3)
cv2.putText(frame, "{}: {:.2f}".format("distance y", distanceY), (10, 200), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3)
#fm = cv2.Laplacian(gray, cv2.CV_64F).var()
#cv2.putText(frame, "{}: {:.2f}".format("blur", fm), (10, 30),
#cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3)
cv2.imshow("Frame", frame)
#cv2.imshow("Process", tresh)
# Press Q on keyboard to exit
key = cv2.waitKey(1)
if key == 32:
cv2.waitKey()
elif key == ord('+'):
dilationVal = dilationVal + 1
elif key == ord('-'):
if dilationVal > 0:
dilationVal = dilationVal - 1
elif key == ord('x'):
rectToSet = 'x'
elif key == ord('y'):
rectToSet = 'y'
elif key == ord('q'):
break
# Break the loop
else:
break
# When everything done, release
# the video capture object
cap.release()
# Closes all the frames
cv2.destroyAllWindows()

@ -1,53 +0,0 @@
import cv2
import numpy as np
drawing = False
point1 = ()
point2 = ()
def mouse_drawing(event, x, y, flags, params):
global point1, point2, drawing
if event == cv2.EVENT_LBUTTONDOWN:
if drawing is False:
drawing = True
point1 = (x, y)
else:
drawing = False
elif event == cv2.EVENT_MOUSEMOVE:
if drawing is True:
point2 = (x, y)
cap = cv2.VideoCapture("/home/mwinter/Portfolio/a_history_of_the_domino_problem/a_history_of_the_domino_problem_source/recs/a_history_of_the_domino_problem_final_documentation_hq.mp4")
# Exit if video not opened.
if not cap.isOpened():
print("Could not open video")
sys.exit()
# Read first frame.
cap.set(cv2.CAP_PROP_POS_FRAMES, 5000)
ok, initFrame = cap.read()
if not ok:
print('Cannot read video file')
sys.exit()
cv2.namedWindow("Frame")
#cv2.setMouseCallback("Frame", mouse_drawing)
while cap.isOpened():
ok, frame = cap.read()
if ok == True:
#if point1 and point2:
# cv2.rectangle(frame, point1, point2, (0, 255, 0))
cv2.imshow("Frame", frame)
else:
break
cap.release()
cv2.destroyAllWindows()

@ -1,9 +0,0 @@
<html>
<head>
<title>Video Streaming Demonstration</title>
</head>
<body>
<h1>Video Streaming Demonstration</h1>
<img src="{{ url_for('video_feed') }}">
</body>
</html>

@ -1,162 +1,221 @@
#This is a proof of concept for motion tracking of the vernier in very early stages
#!/usr/bin/python3
from PyQt5.QtWidgets import QApplication, QWidget, QShortcut
from PyQt5.QtGui import QKeySequence
from PyQt5.QtCore import Qt, QThread, QPoint
import time
import cv2
import sys
from pythonosc.udp_client import SimpleUDPClient
from flask import Flask, render_template, Response
import threading
import argparse
outputFrame = None
lock = threading.Lock()
app = Flask(__name__)
ip = "127.0.0.1"
port = 57120
client = SimpleUDPClient(ip, port) # Create client
# Read video (eventually will be the live capture from the camera)
video = cv2.VideoCapture("/home/mwinter/Portfolio/a_history_of_the_domino_problem/a_history_of_the_domino_problem_source/recs/a_history_of_the_domino_problem_final_documentation_hq.mp4")
# Exit if video not opened.
if not video.isOpened():
print("Could not open video")
sys.exit()
# Read first frame.
video.set(cv2.CAP_PROP_POS_FRAMES, 5000)
ok, initFrame = video.read()
if not ok:
print('Cannot read video file')
sys.exit()
#frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
#frame = cv2.GaussianBlur(frame,(5,5),cv2.BORDER_DEFAULT)
# all this for selecting ROI
#xROI = cv2.selectROI('Tracking', initFrame)
#yROI = cv2.selectROI('Tracking', initFrame)
#print(xROI)
#print(yROI)
#xFine = (xROI[0], xROI[1], xROI[2], xROI[3] / 2)
#xCourse = (xROI[0], xROI[1] + (xROI[3] / 2), xROI[2], xROI[3] / 2)
#yFine = (yROI[0], yROI[1], yROI[2] / 2, yROI[3])
#yCourse = (yROI[0] + (yROI[2] / 2), yROI[1], yROI[2] / 2, yROI[3])
#print(xFine)
#print(yFine)
xFine = (848, 187, 225, 21.0)
yFine = (604, 402, 20.5, 276)
frameCountMod = 0
centroidX = [0, 0]
centroidY = [0, 0]
def track(frame, ROI, centroid, update):
if(update):
crop = frame[int(ROI[1]):int(ROI[1]+ROI[3]), int(ROI[0]):int(ROI[0]+ROI[2])]
crop = cv2.cvtColor(crop, cv2.COLOR_RGB2GRAY)
crop = cv2.GaussianBlur(crop,(7,7),cv2.BORDER_DEFAULT)
#ret, thresh = cv2.threshold(crop, 100, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY)
ret,thresh = cv2.threshold(crop, 50, 255, 0)
M = cv2.moments(thresh)
# calculate x,y coordinate of center
if M["m00"] != 0:
centroid[0] = int(M["m10"] / M["m00"])
centroid[1] = int(M["m01"] / M["m00"])
#else:
# cX, cY = 0, 0
#print(cY)
cv2.circle(frame, (int(ROI[0]) + centroid[0], int(ROI[1]) + centroid[1]), 5, (255, 255, 255), -1)
def detect_motion():
# grab global references to the video stream, output frame, and
# lock variables
global vs, outputFrame, lock
frameCountMod = 0
centroidX = [0, 0]
centroidY = [0, 0]
"""Video streaming generator function."""
while True:
# Read a new frame
ok, frame = video.read()
if not ok:
break
if(frameCountMod == 0):
track(frame, xFine, centroidX, True)
track(frame, yFine, centroidY, True)
xPos = (centroidX[0] / xFine[2]) * 2 - 1
yPos = (centroidY[1] / yFine[3]) * 2 - 1
client.send_message("/trackerpos", [xPos, yPos])
else:
track(frame, xFine, centroidX, False)
track(frame, yFine, centroidY, False)
frameCountMod = (frameCountMod + 1) % 10
cv2.rectangle(frame, (int(xFine[0]), int(xFine[1])), (int(xFine[0]+int(xFine[2])),int(xFine[1]+xFine[3])), (255, 255, 255), 5)
cv2.rectangle(frame, (int(yFine[0]), int(yFine[1])), (int(yFine[0]+int(yFine[2])),int(yFine[1]+yFine[3])), (255, 255, 255), 5)
# Display result
#cv2.imshow("Tracking", frame)
#cv2.imshow("Crop", crop)
with lock:
outputFrame = frame.copy()
# Exit if ESC pressed
#k = cv2.waitKey(1) & 0xff
#if k == 27 :
# cv2.destroyWindow('Tracking')
# break
@app.route('/')
def index():
"""Video streaming home page."""
return render_template('index.html')
def generate():
# grab global references to the output frame and lock variables
global outputFrame, lock
# loop over frames from the output stream
while True:
# wait until the lock is acquired
with lock:
# check if the output frame is available, otherwise skip
# the iteration of the loop
if outputFrame is None:
continue
# encode the frame in JPEG format
(flag, encodedImage) = cv2.imencode(".jpg", outputFrame)
# ensure the frame was successfully encoded
if not flag:
continue
# yield the output frame in the byte format
yield(b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' +
bytearray(encodedImage) + b'\r\n')
@app.route('/video_feed')
def video_feed():
"""Video streaming route. Put this in the src attribute of an img tag."""
return Response(generate(),mimetype='multipart/x-mixed-replace; boundary=frame')
if __name__ == '__main__':
t = threading.Thread(target=detect_motion)
t.daemon = True
t.start()
app.run(host='127.0.0.1', port=5000, threaded=True)
from picamera2 import MappedArray, Picamera2, Preview
from picamera2.previews.qt import QGlPicamera2
import numpy as np
def rectFromPoint(center, len, width, axis):
rect = ((0, 0), (0, 0))
l = int(len/2)
w = int(width/2)
if(axis == 'x'):
rect = ((center[0] - l, center[1] - w), (center[0] + l, center[1] + w))
elif(axis == 'y'):
rect = ((center[0] - w, center[1] - l), (center[0] + w, center[1] + l))
return rect
def rectsFromPoint(center, l1, l2, l3, w, axis):
centerFine = center
fineInner = rectFromPoint(centerFine, l1, w, axis)
fineOuter = rectFromPoint(centerFine, l2, w, axis)
centerCoarse = center
if(axis == 'x'):
centerCoarse = (center[0], center[1] + w)
elif(axis == 'y'):
centerCoarse = (center[0] + w, center[1])
coarse = rectFromPoint(centerCoarse, l3, w, axis)
return [fineInner, fineOuter, coarse, center]
def moveROI(event, x, y, flags, params):
global roiX, roiY, moving, l1, l2, l3, w, selectedAxis
if event == cv2.EVENT_LBUTTONDOWN:
moving = True
elif event==cv2.EVENT_MOUSEMOVE:
if moving==True:
if(selectedAxis == 'x'):
roiX = rectsFromPoint((x, y), l1, l2, l3, w, selectedAxis)
elif(selectedAxis == 'y'):
roiY = rectsFromPoint((x, y), l1, l2, l3, w, selectedAxis)
elif event == cv2.EVENT_LBUTTONUP:
moving = False
def crop(frame, rect):
return frame[rect[0][1]:rect[1][1], rect[0][0]:rect[1][0]]
def replaceCrop(frame, rect, crop):
frame[rect[0][1]:rect[1][1], rect[0][0]:rect[1][0]] = crop
def genDKernel(dVal):
return np.ones((dVal, dVal), np.uint8)
def track(frame, roi, dKernel):
exp = 2
roiFineInner, roiFineOuter, roiCourse, roiCenter = roi
cropFineOuter = crop(frame, roiFineOuter)
cropCoarse = crop(frame, roiCourse)
#gray = cv2.cvtColor(crop, cv2.COLOR_BGR2GRAY)
dilation = cv2.dilate(cropFineOuter, dKernel, iterations=1)
ret,thresh = cv2.threshold(dilation,100,255,cv2.THRESH_BINARY)
replaceCrop(frame, roiFineOuter, thresh)
# this could potentially be made more efficient by cropping from cropFineOuter
cropFineInner = crop(frame, roiFineInner)
meanFine = pow(cropFineInner.mean(), exp)
meanCourse = pow(cropCoarse.mean(), 1)
mean = 0
if(meanCourse > 10):
mean = meanFine
distance = pow(255, exp) - mean
return distance
def drawRect(frame, points):
cv2.rectangle(frame, points[0], points[1], (0, 255, 0))
def drawRoi(frame, roi):
for rect in roi[:3]:
drawRect(frame, rect)
center = roi[3]
cv2.line(frame, (center[0] - 5, center[1]), (center[0] + 5, center[1]), (0, 255, 0), 1)
cv2.line(frame, (center[0], center[1] - 5), (center[0], center[1] + 5), (0, 255, 0), 1)
def picameraToCVTrack():
global roiX, roiY, moving, l1, l2, l3, w, selectedAxis, dilationKernel, calibrate
while True:
frame = picam2.capture_buffer("lores")
frame = frame[:s1 * h1].reshape((h1, s1))
#frame = picam2.capture_array("lores")
#frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2RGB)
distanceX = track(frame, roiX, dilationKernel)
distanceY = track(frame, roiY, dilationKernel)
drawRoi(frame, roiX)
drawRoi(frame, roiY)
cv2.putText(frame, "{}: {:.2f}".format("distance x", distanceX), (10, 100), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3)
cv2.putText(frame, "{}: {:.2f}".format("distance y", distanceY), (10, 200), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3)
if calibrate:
cv2.imshow("Frame", frame)
#cv2.imshow("Process", tresh)
# Press Q on keyboard to exit
key = cv2.waitKey(20)
#if key == 32:
# cv2.waitKey()
if key == ord('+'):
dilationVal = dilationVal + 1
dilationKernel = genDKernel(dilationVal)
elif key == ord('-'):
if dilationVal > 0:
dilationVal = dilationVal - 1
dilationKernel = genDKernel(dilationVal)
elif key == ord('x'):
selectedAxis = 'x'
elif key == ord('y'):
selectedAxis = 'y'
elif key == ord('c'):
if calibrate:
calibrate = False
cv2.destroyAllWindows()
else:
print("hello")
calibrate = True
cv2.startWindowThread()
#elif key == ord('q'):
# break
class TrackerThread(QThread):
def __init__(self, target=None):
super().__init__()
self.target = target
def run(self):
if self.target:
self.target()
class MainWindow(QGlPicamera2):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
trackerThread = TrackerThread(target=picameraToCVTrack)
trackerThread.start()
self.shortcut_close_window = QShortcut(QKeySequence('f'), self)
self.shortcut_close_window.activated.connect(self.goFullscreen)
self.setWindowFlags(Qt.FramelessWindowHint)
self.move(0, 0)
def mousePressEvent(self, event):
self.oldPos = event.globalPos()
def mouseMoveEvent(self, event):
delta = QPoint (event.globalPos() - self.oldPos)
self.move(self.x() + delta.x(), self.y() + delta.y())
self.oldPos = event.globalPos()
def goFullscreen(self):
if self.isFullScreen():
#self.setWindowFlags(self._flags)
self.showNormal()
else:
#self._flags = self.windowFlags()
#self.setWindowFlags(Qt.WindowCloseButtonHint | Qt.WindowType_Mask)
self.showFullScreen()
picam2 = Picamera2()
#picam2.start_preview(Preview.QTGL)
#max resolution is (4056, 3040) which is more like 10 fps
config = picam2.create_preview_configuration(main={"size": (2028, 1520)}, lores={"size": (1920, 1440), "format": "YUV420"})
picam2.configure(config)
app = QApplication([])
qpicamera2 = MainWindow(picam2, width=1920, height=1440, keep_ar=False)
qpicamera2.setWindowTitle("Qt Picamera2 App")
selectedAxis = 'x'
moving = False
l1 = 100
l2 = 300
l3 = 40
w = 20
roiXCenter = (960, 195)
roiYCenter = (615, 530)
roiX = rectsFromPoint(roiXCenter, l1, l2, l3, w, 'x')
roiY = rectsFromPoint(roiYCenter, l1, l2, l3, w, 'y')
dilationVal = 75
dilationKernel = genDKernel(dilationVal)
calibrate = True
cv2.startWindowThread()
cv2.namedWindow("Frame")
cv2.setMouseCallback("Frame", moveROI)
(w0, h0) = picam2.stream_configuration("main")["size"]
(w1, h1) = picam2.stream_configuration("lores")["size"]
s1 = picam2.stream_configuration("lores")["stride"]
picam2.start()
qpicamera2.show()
app.exec()

@ -1,113 +0,0 @@
# importing libraries
import cv2
import numpy as np
drawing = False
point1 = ()
point2 = ()
def mouse_drawing(event, x, y, flags, params):
global point1, point2, drawing
if event == cv2.EVENT_LBUTTONDOWN:
if drawing is False:
drawing = True
point1 = (x, y)
else:
drawing = False
elif event == cv2.EVENT_MOUSEMOVE:
if drawing is True:
point2 = (x, y)
#xFine = (848, 187, 225, 21.0)
#yFine = (604, 402, 20.5, 276)
xFine = (848, 187, 848 + 225, 187 + 21.0)
yFine = (604, 402, 604 + 20.5, 402 + 276)
frameCountMod = 0
centroidX = [0, 0]
centroidY = [0, 0]
def track(frame, ROI, centroid, update):
if(update):
crop = frame[int(ROI[1]):int(ROI[3]), int(ROI[0]):int(ROI[2])]
crop = cv2.cvtColor(crop, cv2.COLOR_RGB2GRAY)
crop = cv2.GaussianBlur(crop,(7,7),cv2.BORDER_DEFAULT)
ret,thresh = cv2.threshold(crop, 50, 255, 0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
# calculate moments for each contour
M = cv2.moments(c)
# calculate x,y coordinate of center
if M["m00"] != 0:
centroid[0] = int(M["m10"] / M["m00"])
centroid[1] = int(M["m01"] / M["m00"])
else:
centroid[0], centroid[1] = 0, 0
#cv2.circle(img, (cX, cY), 5, (255, 255, 255), -1)
cv2.circle(frame, (int(ROI[0]) + centroid[0], int(ROI[1]) + centroid[1]), 3, (0, 255, 0), -1)
cv2.namedWindow("Frame")
cv2.setMouseCallback("Frame", mouse_drawing)
# Create a VideoCapture object and read from input file
cap = cv2.VideoCapture("/home/mwinter/Portfolio/a_history_of_the_domino_problem/a_history_of_the_domino_problem_source/recs/a_history_of_the_domino_problem_final_documentation_hq.mp4")
cap.set(cv2.CAP_PROP_POS_FRAMES, 10000)
# Check if camera opened successfully
if (cap.isOpened()== False):
print("Error opening video file")
frameCountMod = 0
centroidX = [0, 0]
centroidY = [0, 0]
# Read until video is completed
while(cap.isOpened()):
# Capture frame-by-frame
ret, frame = cap.read()
if ret == True:
# Display the resulting frame
if(frameCountMod == 0):
track(frame, xFine, centroidX, True)
track(frame, yFine, centroidY, True)
xPos = (centroidX[0] / xFine[2]) * 2 - 1
yPos = (centroidY[1] / yFine[3]) * 2 - 1
else:
track(frame, xFine, centroidX, False)
track(frame, yFine, centroidY, False)
frameCountMod = (frameCountMod + 1) % 10
cv2.rectangle(frame, (int(xFine[0]), int(xFine[1])), (int(xFine[2]),int(xFine[3])), (0, 255, 0))
cv2.rectangle(frame, (int(yFine[0]), int(yFine[1])), (int(yFine[2]),int(yFine[3])), (0, 255, 0))
if point1 and point2:
#cv2.rectangle(frame, point1, point2, (0, 255, 0))
xFine = (point1[0], point1[1], point2[0], point2[1])
cv2.imshow("Frame", frame)
# Press Q on keyboard to exit
if cv2.waitKey(25) & 0xFF == ord('q'):
break
# Break the loop
else:
break
# When everything done, release
# the video capture object
cap.release()
# Closes all the frames
cv2.destroyAllWindows()

@ -1,110 +0,0 @@
# importing libraries
import cv2
import numpy as np
drawing = False
point1 = ()
point2 = ()
def mouse_drawing(event, x, y, flags, params):
global point1, point2, drawing
if event == cv2.EVENT_LBUTTONDOWN:
if drawing is False:
drawing = True
point1 = (x, y)
else:
drawing = False
elif event == cv2.EVENT_MOUSEMOVE:
if drawing is True:
point2 = (x, y)
#xFine = (848, 187, 225, 21.0)
#yFine = (604, 402, 20.5, 276)
xFine = (848, 187, 848 + 225, 187 + 21.0)
yFine = (604, 402, 604 + 20.5, 402 + 276)
frameCountMod = 0
centroidX = [0, 0]
centroidY = [0, 0]
def track(frame, ROI, centroid, update):
if(update):
crop = frame[int(ROI[1]):int(ROI[3]), int(ROI[0]):int(ROI[2])]
crop = cv2.cvtColor(crop, cv2.COLOR_RGB2GRAY)
crop = cv2.GaussianBlur(crop,(7,7),cv2.BORDER_DEFAULT)
#ret, thresh = cv2.threshold(crop, 100, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY)
ret,thresh = cv2.threshold(crop, 50, 255, 0)
M = cv2.moments(thresh)
# calculate x,y coordinate of center
if M["m00"] != 0:
centroid[0] = int(M["m10"] / M["m00"])
centroid[1] = int(M["m01"] / M["m00"])
#else:
# cX, cY = 0, 0
#print(cY)
cv2.circle(frame, (int(ROI[0]) + centroid[0], int(ROI[1]) + centroid[1]), 3, (0, 255, 0), -1)
cv2.namedWindow("Frame")
cv2.setMouseCallback("Frame", mouse_drawing)
# Create a VideoCapture object and read from input file
cap = cv2.VideoCapture("/home/mwinter/Portfolio/a_history_of_the_domino_problem/a_history_of_the_domino_problem_source/recs/a_history_of_the_domino_problem_final_documentation_hq.mp4")
cap.set(cv2.CAP_PROP_POS_FRAMES, 10000)
# Check if camera opened successfully
if (cap.isOpened()== False):
print("Error opening video file")
frameCountMod = 0
centroidX = [0, 0]
centroidY = [0, 0]
# Read until video is completed
while(cap.isOpened()):
# Capture frame-by-frame
ret, frame = cap.read()
if ret == True:
# Display the resulting frame
if(frameCountMod == 0):
track(frame, xFine, centroidX, True)
track(frame, yFine, centroidY, True)
xPos = (centroidX[0] / xFine[2]) * 2 - 1
yPos = (centroidY[1] / yFine[3]) * 2 - 1
else:
track(frame, xFine, centroidX, False)
track(frame, yFine, centroidY, False)
frameCountMod = (frameCountMod + 1) % 3
cv2.rectangle(frame, (int(xFine[0]), int(xFine[1])), (int(xFine[2]),int(xFine[3])), (0, 255, 0))
cv2.rectangle(frame, (int(yFine[0]), int(yFine[1])), (int(yFine[2]),int(yFine[3])), (0, 255, 0))
if point1 and point2:
#cv2.rectangle(frame, point1, point2, (0, 255, 0))
xFine = (point1[0], point1[1], point2[0], point2[1])
cv2.imshow("Frame", frame)
# Press Q on keyboard to exit
if cv2.waitKey(25) & 0xFF == ord('q'):
break
# Break the loop
else:
break
# When everything done, release
# the video capture object
cap.release()
# Closes all the frames
cv2.destroyAllWindows()

@ -1,60 +0,0 @@
# importing libraries
import cv2
import numpy as np
drawing = False
point1 = ()
point2 = ()
def mouse_drawing(event, x, y, flags, params):
global point1, point2, drawing
if event == cv2.EVENT_LBUTTONDOWN:
if drawing is False:
drawing = True
point1 = (x, y)
else:
drawing = False
elif event == cv2.EVENT_MOUSEMOVE:
if drawing is True:
point2 = (x, y)
cv2.namedWindow("Frame")
cv2.setMouseCallback("Frame", mouse_drawing)
# Create a VideoCapture object and read from input file
cap = cv2.VideoCapture("/home/mwinter/Portfolio/a_history_of_the_domino_problem/a_history_of_the_domino_problem_source/recs/a_history_of_the_domino_problem_final_documentation_hq.mp4")
# Check if camera opened successfully
if (cap.isOpened()== False):
print("Error opening video file")
# Read until video is completed
while(cap.isOpened()):
# Capture frame-by-frame
ret, frame = cap.read()
if ret == True:
# Display the resulting frame
if point1 and point2:
cv2.rectangle(frame, point1, point2, (0, 255, 0))
cv2.imshow("Frame", frame)
# Press Q on keyboard to exit
if cv2.waitKey(25) & 0xFF == ord('q'):
break
# Break the loop
else:
break
# When everything done, release
# the video capture object
cap.release()
# Closes all the frames
cv2.destroyAllWindows()

@ -0,0 +1,175 @@
\version "2.24.1"
genStaff =
#(define-music-function (parser location part)
(string?)
(let * ((file (string-append "includes/ammann_part_" part ".ly")))
#{
\new Staff \with {
instrumentName = #part
shortInstrumentName = #part
}
<<
\include #file
>>
#}))
\paper {
#(set-paper-size "a4" 'portrait)
top-margin = 1 \cm
bottom-margin = 1 \cm
left-margin = 1.75 \cm
top-system-spacing =
#'((basic-distance . 15 )
(minimum-distance . 15 )
(padding . 0 )
(stretchability . 0))
last-bottom-spacing =
#'((basic-distance . 15 )
(minimum-distance . 15 )
(padding . 0 )
(stretchability . 0))
systems-per-page = 4
print-page-number = ##t
oddHeaderMarkup = \markup { \unless \on-first-page {"(ammann)"}}
evenHeaderMarkup = \markup { \unless \on-first-page {"(ammann)"}}
oddFooterMarkup = \markup { \fill-line {
\concat {
"-"
\fontsize #1.5
\fromproperty #'page:page-number-string
"-"}}}
evenFooterMarkup = \markup { \fill-line {
\concat {
"-"
\fontsize #1.5
\fromproperty #'page:page-number-string
"-"}}}
}
\header {
title = \markup { \italic {ammann}}
subtitle = \markup { \normal-text { from \italic{a history of the domino the problem}}}
composer = \markup \right-column {"michael winter" "(schloss solitude, stuttgart and calle monclova 62, mexico city; 2018-19)"}
tagline = ""
}
#(set-global-staff-size 11)
\layout {
indent = 0.0\cm
line-width = 17\cm
%ragged-last = ##t
\context {
\Score
\override BarNumber.extra-offset = #'(0 . 4)
\override BarNumber.stencil = #(make-stencil-circler 0.1 0.25 ly:text-interface::print)
\override RehearsalMark.direction = #DOWN
rehearsalMarkFormatter = #format-mark-box-numbers
}
\context {
\Staff
\override VerticalAxisGroup.staff-staff-spacing =
#'((basic-distance . 15 )
(minimum-distance . 15 )
(padding . 0 )
(stretchability . 0))
\override TimeSignature.font-size = #2
\override TimeSignature.break-align-symbol = #'clef
\override TimeSignature.X-offset =
#ly:self-alignment-interface::x-aligned-on-self
\override TimeSignature.self-alignment-X = #LEFT
%\override TimeSignature.after-line-breaking =
% #shift-right-at-line-begin
\override TimeSignature.Y-offset = #11
\override TimeSignature.extra-offset = #'(2 . 0)
}
\context {
\StaffGroup
\name "SemiStaffGroup"
\consists "Span_bar_engraver"
\override SpanBar.stencil =
#(lambda (grob)
(if (string=? (ly:grob-property grob 'glyph-name) "|")
(set! (ly:grob-property grob 'glyph-name) ""))
(ly:span-bar::print grob))
}
\context {
\Score
\accepts SemiStaffGroup
}
}
\score {
%showLastLength = R1*128
\new Score
%\with{ proportionalNotationDuration = #(ly:make-moment 1 16) }
<<
\new SemiStaffGroup {
<<
\new Staff \with {
instrumentName = #"4"
shortInstrumentName = #"4"
midiInstrument = #"clarinet"
}
<<
\transpose c c'
\include "includes/ammann_part_4.ly"
>>
\new Staff \with {
instrumentName = #"3"
shortInstrumentName = #"3"
midiInstrument = #"clarinet"
\remove "Time_signature_engraver"
}
<<
\clef bass
\transpose c c,
\include "includes/ammann_part_5.ly"
>>
\new Staff \with {
instrumentName = #"2"
shortInstrumentName = #"2"
midiInstrument = #"clarinet"
\remove "Time_signature_engraver"
}
<<
\include "includes/ammann_part_6.ly"
>>
\new Staff \with {
instrumentName = #"1"
shortInstrumentName = #"1"
midiInstrument = #"clarinet"
\remove "Time_signature_engraver"
}
<<
\clef bass
\transpose c c,,
\include "includes/ammann_part_7.ly"
>>
%\genStaff #"0"
%\genStaff #"1"
%\genStaff #"2"
%\genStaff #"3"
%\genStaff #"4"
%\genStaff #"5"
>>
}
>>
\layout { }
%\midi { }
}

@ -0,0 +1,193 @@
\version "2.24.1"
genStaff =
#(define-music-function (parser location part)
(string?)
(let * ((file (string-append "includes/ammann_part_" part ".ly")))
#{
\new Staff \with {
instrumentName = #part
shortInstrumentName = #part
}
<<
\include #file
>>
#}))
\paper {
#(set-paper-size "a4" 'portrait)
top-margin = 1 \cm
bottom-margin = 1 \cm
left-margin = 1.75 \cm
top-system-spacing =
#'((basic-distance . 15 )
(minimum-distance . 15 )
(padding . 0 )
(stretchability . 0))
last-bottom-spacing =
#'((basic-distance . 15 )
(minimum-distance . 15 )
(padding . 0 )
(stretchability . 0))
systems-per-page = 3
print-page-number = ##t
oddHeaderMarkup = \markup { \unless \on-first-page {"(ammann)"}}
evenHeaderMarkup = \markup { \unless \on-first-page {"(ammann)"}}
oddFooterMarkup = \markup { \fill-line {
\concat {
"-"
\fontsize #1.5
\fromproperty #'page:page-number-string
"-"}}}
evenFooterMarkup = \markup { \fill-line {
\concat {
"-"
\fontsize #1.5
\fromproperty #'page:page-number-string
"-"}}}
}
\header {
title = \markup { \italic {ammann}}
subtitle = \markup { \normal-text { from \italic{a history of the domino the problem}}}
composer = \markup \right-column {"michael winter" "(schloss solitude, stuttgart and calle monclova 62, mexico city; 2018-19)"}
tagline = ""
}
#(set-global-staff-size 11)
\layout {
indent = 0.0\cm
line-width = 17\cm
%ragged-last = ##t
\context {
\Score
\override BarNumber.extra-offset = #'(0 . 4)
\override BarNumber.stencil = #(make-stencil-circler 0.1 0.25 ly:text-interface::print)
\override RehearsalMark.direction = #DOWN
rehearsalMarkFormatter = #format-mark-box-numbers
}
\context {
\Staff
\override VerticalAxisGroup.staff-staff-spacing =
#'((basic-distance . 17 )
(minimum-distance . 17 )
(padding . 0 )
(stretchability . 0))
\override TimeSignature.font-size = #2
\override TimeSignature.break-align-symbol = #'clef
\override TimeSignature.X-offset =
#ly:self-alignment-interface::x-aligned-on-self
\override TimeSignature.self-alignment-X = #LEFT
%\override TimeSignature.after-line-breaking =
% #shift-right-at-line-begin
\override TimeSignature.Y-offset = #9
\override TimeSignature.extra-offset = #'(2 . 0)
}
\context {
\StaffGroup
\name "SemiStaffGroup"
\consists "Span_bar_engraver"
\override SpanBar.stencil =
#(lambda (grob)
(if (string=? (ly:grob-property grob 'glyph-name) "|")
(set! (ly:grob-property grob 'glyph-name) ""))
(ly:span-bar::print grob))
}
\context {
\Score
\accepts SemiStaffGroup
}
}
\score {
%showLastLength = R1*128
\new Score
%\with{ proportionalNotationDuration = #(ly:make-moment 1 16) }
<<
\new SemiStaffGroup {
<<
\new Staff \with {
instrumentName = #"3+4↑"
shortInstrumentName = #"3+4↑"
midiInstrument = #"clarinet"
\consists Merge_rests_engraver
}
<<
\transpose c c
\include "includes/ammann_part_4_up.ly"
\\
\transpose c c,
\include "includes/ammann_part_5_up.ly"
>>
\new Staff \with {
instrumentName = #"3+4↓"
shortInstrumentName = #"3+4↓"
midiInstrument = #"clarinet"
\remove "Time_signature_engraver"
\consists Merge_rests_engraver
}
<<
\clef bass
\transpose c c
\include "includes/ammann_part_4_down.ly"
\\
\clef bass
\transpose c c,
\include "includes/ammann_part_5_down.ly"
>>
\new Staff \with {
instrumentName = #"1+2↑"
shortInstrumentName = #"1+2↑"
midiInstrument = #"clarinet"
\remove "Time_signature_engraver"
\consists Merge_rests_engraver
}
<<
\transpose c c
\include "includes/ammann_part_6_up.ly"
\\
\transpose c c,
\include "includes/ammann_part_7_up.ly"
>>
\new Staff \with {
instrumentName = #"1+2↓"
shortInstrumentName = #"1+2↓"
midiInstrument = #"clarinet"
\remove "Time_signature_engraver"
\consists Merge_rests_engraver
}
<<
\clef bass
\transpose c c
\include "includes/ammann_part_6_down.ly"
\\
\clef bass
\transpose c c,
\include "includes/ammann_part_7_down.ly"
>>
%\genStaff #"0"
%\genStaff #"1"
%\genStaff #"2"
%\genStaff #"3"
%\genStaff #"4"
%\genStaff #"5"
>>
}
>>
\layout { }
%\midi { }
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,208 @@
\version "2.24.1"
genStaff =
#(define-music-function (parser location part)
(string?)
(let * ((file (string-append "includes/berger_part_" part ".ly")))
#{
\new Staff \with {
instrumentName = #part
shortInstrumentName = #part
}
<<
\include #file
>>
#}))
\paper {
#(set-paper-size "a4" 'portrait)
top-margin = 1 \cm
bottom-margin = 1 \cm
left-margin = 1.75 \cm
top-system-spacing =
#'((basic-distance . 25 )
(minimum-distance . 25 )
(padding . 0 )
(stretchability . 0))
last-bottom-spacing =
#'((basic-distance . 15 )
(minimum-distance . 15 )
(padding . 0 )
(stretchability . 0))
systems-per-page = 3
print-page-number = ##t
oddHeaderMarkup = \markup { \unless \on-first-page {"(berger-knuth)"}}
evenHeaderMarkup = \markup { \unless \on-first-page {"(berger-knuth)"}}
oddFooterMarkup = \markup { \fill-line {
\concat {
"-"
\fontsize #1.5
\fromproperty #'page:page-number-string
"-"}}}
evenFooterMarkup = \markup { \fill-line {
\concat {
"-"
\fontsize #1.5
\fromproperty #'page:page-number-string
"-"}}}
}
\header {
title = \markup { \italic {berger-knuth}}
subtitle = \markup { \normal-text { from \italic{a history of the domino the problem}}}
composer = \markup \right-column {"michael winter" "(schloss solitude, stuttgart and calle monclova 62, mexico city; 2018-19)"}
tagline = ""
}
#(set-global-staff-size 11)
\layout {
indent = 0.0\cm
line-width = 17\cm
%ragged-last = ##t
\context {
\Score
\override BarNumber.extra-offset = #'(0 . 4)
\override BarNumber.stencil = #(make-stencil-circler 0.1 0.25 ly:text-interface::print)
\override RehearsalMark.direction = #DOWN
rehearsalMarkFormatter = #format-mark-box-numbers
}
\context {
\Staff
\override VerticalAxisGroup.staff-staff-spacing =
#'((basic-distance . 16 )
(minimum-distance . 16 )
(padding . 0 )
(stretchability . 0))
\override TimeSignature.font-size = #2
\override TimeSignature.break-align-symbol = #'clef
\override TimeSignature.X-offset =
#ly:self-alignment-interface::x-aligned-on-self
\override TimeSignature.self-alignment-X = #LEFT
%\override TimeSignature.after-line-breaking =
% #shift-right-at-line-begin
\override TimeSignature.Y-offset = #9
\override TimeSignature.extra-offset = #'(2 . 0)
}
\context {
\StaffGroup
\name "SemiStaffGroup"
\consists "Span_bar_engraver"
\override SpanBar.stencil =
#(lambda (grob)
(if (string=? (ly:grob-property grob 'glyph-name) "|")
(set! (ly:grob-property grob 'glyph-name) ""))
(ly:span-bar::print grob))
}
\context {
\Score
\accepts SemiStaffGroup
}
}
\score{
%showLastLength = R1*128
\new Score
%\with{ proportionalNotationDuration = #(ly:make-moment 1 16) }
<<
\new SemiStaffGroup {
<<
\new Staff \with {
instrumentName = #"1a"
shortInstrumentName = #"1a"
midiInstrument = #"flute"
}
<<
\include "includes/berger_part_3.ly"
>>
\new Staff \with {
instrumentName = #"2a"
shortInstrumentName = #"2a"
midiInstrument = #"clarinet"
\remove "Time_signature_engraver"
}
<<
\include "includes/berger_part_2.ly"
>>
\new Staff \with {
instrumentName = #"3a"
shortInstrumentName = #"3a"
midiInstrument = #"viola"
\remove "Time_signature_engraver"
}
<<
\include "includes/berger_part_1.ly"
>>
>>
}
\new SemiStaffGroup {
<<
%{
\new Staff \with {
instrumentName = #"1b"
shortInstrumentName = #"1b"
midiInstrument = #"cello"
\remove "Time_signature_engraver"
}
<<
\include "includes/berger_part_7.ly"
>>
\new Staff \with {
instrumentName = #"2b"
shortInstrumentName = #"2b"
midiInstrument = #"saxophone"
\remove "Time_signature_engraver"
}
<<
\include "includes/berger_part_6.ly"
>>
%}
\new Staff \with {
instrumentName = #"1b + 2b"
shortInstrumentName = #"1b + 2b"
midiInstrument = #"cello"
\remove "Time_signature_engraver"
}
<<
\override DynamicLineSpanner.direction = #UP
\include "includes/berger_part_7.ly"
\\
\include "includes/berger_part_6.ly"
>>
\new Staff \with {
instrumentName = #"3b"
shortInstrumentName = #"3b"
midiInstrument = #"bassoon"
\remove "Time_signature_engraver"
}
<<
\include "includes/berger_part_5.ly"
>>
%\genStaff #"0"
%\genStaff #"1"
%\genStaff #"2"
%\genStaff #"3"
%\genStaff #"4"
%\genStaff #"5"
>>
}
>>
%\midi{}
\layout{}
}

@ -0,0 +1 @@
jaendel-rao is the only score that remains pegged to lilypond 2.19.81, please use the that version.

@ -0,0 +1,300 @@
(
~ammannTranscribe = {arg seqs;
var dir, basePath, subTiling, tileMap, tiles, genTileMap, odds, harms, amps;
//thisThread.randSeed = 100;
//dir = thisProcess.nowExecutingPath.dirname;
//basePath = dir +/+ ".." +/+ "score" +/+ "lilypond_v2.24_update" +/+ "ammann_distributed";
basePath = "/home/mwinter/Portfolio/a_history_of_the_domino_problem/a_history_of_the_domino_problem_source/score/lilypond_v2.24_update/ammann_distributed";
seqs.do({arg part, p;
var lilyFile, lilyString, lastNote, lastTimeSig, lastClef, lastDynamic, beatCountTotal;
//create file
lilyFile = File(basePath +/+ "includes" +/+ "ammann_" ++ "part_" ++ p.asString ++ ".ly".standardizePath,"w");
//start lilypond directives
lilyString = "";
lilyString = lilyString ++ "{\n\\set tupletFullLength = ##t\n"; //"\\set Score.markFormatter = #format-mark-box-numbers\n";
//lilyString = lilyString ++ "{\n";
//lilyString = lilyString + "\\tempo 4 = 60 \n";
lilyString = lilyString ++ "\n\\tempo \\markup {
\\concat {
\\smaller \\general-align #Y #DOWN
\\note #\"4\" #1 \\normal-text \" ≈ 60\"
}}\n";
lastNote = "r";
lastTimeSig = "";
lastClef = "\\clef treble ";
lastDynamic = "";
beatCountTotal = 0;
part.size.do({arg nIndex;
var dirs, del, dur, sustain, harm, amp, quant, note, beatCount, durUnit, measureDur, timeSig, clef, delayGroup, tuplet, dynamic, octFlag = false;
dirs = part[nIndex];
del = dirs[0][0];
dur = dirs[0][1];
sustain = dirs[1, 1]; //not used
harm = dirs[2][1];
amp = dirs[3][1];
quant = dirs[4];
/*
if(amp != 0, {
note = ["c", "cis", "d", "dis", "e", "f", "fis", "g", "gis", "a", "ais", "b"][((55 * harm).cpsmidi % 12).trunc.asInteger];
note = note ++ [",,", ",", "", "'", "''"][((55 * if(harm >= 8, {harm / 2}, {harm})).cpsmidi / 12).trunc.asInteger - 2];
}, {note = "r"});
*/
if(amp != 0, {
note = ["c", "cih", "cis", "deh", "d", "dih", "dis", "eeh", "e", "eih", "f", "fih", "fis", "geh", "g", "gih", "gis", "aeh", "a", "aih", "ais", "beh", "b", "bih"][((55 * harm).cpsmidi % 12).round(0.5) * 2];
note = note ++ [",,", ",", "", "'", "''", "'''", "''''"][((55 * if(harm >= 8, {harm /* / 2 */}, {harm})).cpsmidi / 12).trunc.asInteger - 2];
}, {note = "r"});
/*
if((amp == 0) || (harm < 8) , {note = "r"}, {
note = ["c", "cih", "cis", "deh", "d", "dih", "dis", "eeh", "e", "eih", "f", "fih", "fis", "geh", "g", "gih", "gis", "aeh", "a", "aih", "ais", "beh", "b", "bih"][((55 * harm).cpsmidi % 12).round(0.5) * 2];
//if(p == 4, {(harm + " sdfsdfsd").postln});
note = note ++ [",,", ",", "", "'", "''", "'''", "''''"][((55 * if(harm >= 8, {harm /* / 2 */}, {harm})).cpsmidi / 12).trunc.asInteger - 2];
});
*/
//tmp note vals
//note = ["c'", "d'", "e'", "f'", "g'", "a'", "b'", "c''", "d''", "e''", "f''", "g''", "a''", "b''", "c'''", "d'''"][harm];
beatCount = 0;
durUnit = 0.25;
measureDur = del + dur;
//put in a tie if there is a delay
if((del > 0) && (nIndex > 0) && (lastNote != "r"), {lilyString = lilyString ++ "~ "});
if(lilyString.keep(-4) == "} ~ ", {lilyString = lilyString.drop(-4) ++ "~ } "});
//double bar
if(((nIndex % 32) == 0) && (nIndex != 0), {lilyString = lilyString ++ "\\bar \"||\" "});
//bar check
if(nIndex != 0, {lilyString = lilyString ++ " | " ++ "%{ noteIndex: " ++ nIndex.asString ++ " beat: " ++ beatCountTotal ++ " %} "});
//rehearsal mark
if((nIndex % 32) == 0, {lilyString = lilyString ++ "\\mark \\default "});
//set time signature for each measure
timeSig = "\\numericTimeSignature \\time " ++ if((measureDur / 0.5 % 2) == 0, {measureDur.trunc.asInteger.asString ++ "/4 "},
{(measureDur / 0.5).trunc.asInteger.asString ++ "/8 "});
if(lastTimeSig != timeSig, {lilyString = lilyString ++ timeSig}, {lilyString = lilyString ++ "%{" ++ timeSig ++ "%} "});
lastTimeSig = timeSig;
tuplet = case
{quant == 0.25} {[1/4, " "]}
{quant == (1/3)} {[1/6, "3\/2 "]}
{quant == (1/5)} {[1/5, "5\/4 "]};
//put any quarter notes held from the last measure
if(del.trunc.asInteger >= 1, {
beatCount = beatCount + del.trunc.asInteger;
lilyString = lilyString ++ del.trunc.asInteger.collect({arg index; lastNote ++ "4 " ++
if(((del.frac / quant) >= 1) && (lastNote != "r"), {"~ "}, {""})}).join
});
//transition from last note to new note
if((del.frac / quant) >= 1, {var lastNoteFrac, noteFrac;
beatCount = beatCount + 1;
//only start a tuplet if necessary
if(quant != 0.25, {lilyString = lilyString ++ "\\tuplet " ++ tuplet[1] + " { "});
//end of last note
lastNoteFrac = switch((del.frac / tuplet[0]).round.asInteger, 1, {"16 "}, 2, {"8 "}, 3, {"8. "}, 4, {"4 "});
lilyString = lilyString ++ lastNote ++ lastNoteFrac;
lilyString = lilyString ++ "%{notechange%} ";
//put clef if necessary
if(amp != 0, {
clef = if((55 * harm).cpsmidi >= 57, {"\\clef treble "}, {"\\clef bass "});
if(lastClef != clef, {lilyString = lilyString + clef});
lastClef = clef;
});
//beginning of new note
noteFrac = switch(((if(beatCount > measureDur, {measureDur.frac}, {1}) - del.frac) / tuplet[0]).round.asInteger, 1, {"16 "}, 2, {"8 "}, 3, {"8. "}, 4, {"4 "});
dynamic = if(amp == 0.06, {"\\mf "}, {"\\p "});
lilyString = lilyString ++ note ++ noteFrac ++
if((note != "r"), {if(harm >= 8, {"upp "}, {"down "})}, {""}) ++
if((lastDynamic != dynamic) && (note != "r"), {lastDynamic = dynamic; dynamic}, {""}) ++
if((((measureDur - beatCount) / 0.5).trunc.asInteger > 0) && (note != "r"), {"~ "}, {""});
if(quant != 0.25, {lilyString = lilyString ++ " } "});
octFlag = false;
}, {
lilyString = lilyString ++ "%{notechange%} ";
//put clef if necessary
if(amp != 0, {
clef = if((55 * harm).cpsmidi >= 57, {"\\clef treble "}, {"\\clef bass "});
if(lastClef != clef, {lilyString = lilyString + clef});
lastClef = clef;
});
octFlag = true;
});
dynamic = if(amp == 0.06, {"\\mf "}, {"\\p "});
lilyString = lilyString ++ (measureDur - beatCount).trunc.asInteger.collect({arg b; beatCount = beatCount + 1; note ++ "4 " ++
if(octFlag && (b == 0) && (note != "r"), {if(harm >= 8, {"upp "}, {"down "})}, {""}) ++
if((lastDynamic != dynamic) && (note != "r"), {lastDynamic = dynamic; dynamic}, {""}) ++
if(((measureDur - beatCount) > 0) && (note != "r"), {"~ "}, {""});
}).join;
if((measureDur - beatCount) > 0, {
lilyString = lilyString ++ ((measureDur - beatCount).frac / 0.5).trunc.asInteger.collect({note ++ "8 "}).join});
beatCountTotal = beatCountTotal + measureDur;
lastNote = note
});
lilyString.findRegexp(
"([a-g]|[a-g]+is|[a-g]+ih|[a-g]+eh|r)(,,|,|'|''|)4 (upp |down |)(\\\\mf |\\\\p |)(~ )*" ++
"([a-g]|[a-g]+is|[a-g]+ih|[a-g]+eh|r)(,,|,|'|''|)4 (\\\\mf |\\\\p |)(~ )*" ++
"([a-g]|[a-g]+is|[a-g]+ih|[a-g]+eh|r)(,,|,|'|''|)4 (\\\\mf |\\\\p |)(~ )*" ++
"([a-g]|[a-g]+is|[a-g]+ih|[a-g]+eh|r)(,,|,|'|''|)4").clump(16).do({arg match;
if(
[
match[1][1] ++ match[2][1],
match[6][1] ++ match[7][1],
match[10][1] ++ match[11][1],
match[14][1] ++ match[15][1]
].asSet.size == 1, {lilyString = lilyString.replace(match[0][1], match[1][1] ++ match[2][1] ++ "1" ++ match[3][1] ++ match[4][1])
})
});
lilyString.findRegexp(
"([a-g]|[a-g]+is|[a-g]+ih|[a-g]+eh|r)(,,|,|'|''|)4 (upp |down |)(\\\\mf |\\\\p |)(~ )*" ++
"([a-g]|[a-g]+is|[a-g]+ih|[a-g]+eh|r)(,,|,|'|''|)4 (\\\\mf |\\\\p |)(~ )*" ++
"([a-g]|[a-g]+is|[a-g]+ih|[a-g]+eh|r)(,,|,|'|''|)4").clump(12).do({arg match;
if(
[
match[1][1] ++ match[2][1],
match[6][1] ++ match[7][1],
match[10][1] ++ match[11][1]
].asSet.size == 1, {lilyString = lilyString.replace(match[0][1], match[1][1] ++ match[2][1] ++ "2." ++ match[3][1] ++ match[4][1])
})
});
lilyString.findRegexp(
"([a-g]|[a-g]+is|[a-g]+ih|[a-g]+eh|r)(,,|,|'|''|)4 (upp |down |)(\\\\mf |\\\\p |)(~ )*" ++
"([a-g]|[a-g]+is|[a-g]+ih|[a-g]+eh|r)(,,|,|'|''|)4").clump(8).do({arg match;
if(
[
match[1][1] ++ match[2][1],
match[6][1] ++ match[7][1]
].asSet.size == 1, {lilyString = lilyString.replace(match[0][1], match[1][1] ++ match[2][1] ++ "2" ++ match[3][1] ++ match[4][1])
})
});
lilyString.findRegexp(
"([a-g]|[a-g]+is|[a-g]+ih|[a-g]+eh|r)(,,|,|'|''|)8 (upp |down |)(\\\\mf |\\\\p |)(~ )*" ++
"([a-g]|[a-g]+is|[a-g]+ih|[a-g]+eh|r)(,,|,|'|''|)8").clump(8).do({arg match;
if(
[
match[1][1] ++ match[2][1],
match[6][1] ++ match[7][1]
].asSet.size == 1, {lilyString = lilyString.replace(match[0][1], match[1][1] ++ match[2][1] ++ "4" ++ match[3][1] ++ match[4][1])
})
});
lilyString.findRegexp(
"([a-g]|[a-g]+is|[a-g]+ih|[a-g]+eh|r)(,,|,|'|''|)4 (upp |down |)(\\\\mf |\\\\p |)(~ )*" ++
"([a-g]|[a-g]+is|[a-g]+ih|[a-g]+eh|r)(,,|,|'|''|)8 ").clump(8).do({arg match;
if(
[
match[1][1] ++ match[2][1],
match[6][1] ++ match[7][1]
].asSet.size == 1, {lilyString = lilyString.replace(match[0][1], match[1][1] ++ match[2][1] ++ "4. " ++ match[3][1] ++ match[4][1])
})
});
lilyString.findRegexp(
"([a-g]|[a-g]+is|[a-g]+ih|[a-g]+eh|r)(,,|,|'|''|)8 (upp |down |)(\\\\mf |\\\\p |)(~ )*" ++
"([a-g]|[a-g]+is|[a-g]+ih|[a-g]+eh|r)(,,|,|'|''|)4 ").clump(8).do({arg match;
if(
[
match[1][1] ++ match[2][1],
match[6][1] ++ match[7][1]
].asSet.size == 1, {lilyString = lilyString.replace(match[0][1], match[1][1] ++ match[2][1] ++ "4. " ++ match[3][1] ++ match[4][1])
})
});
//rest consolidation for half parts
lilyString.findRegexp("\\\\tuplet\\h*\\d/\\d\\h*{\\h*r\\d.?\\h*%{notechange%}\\h*r\\d.?\\h*}").do({arg match;
lilyString = lilyString.replace(match[1], "r4")
});
lilyString.findRegexp("\\\\time\\h*\\d/\\d\\h*%?}?\\h*((%{notechange%})?\\h*r\\d.?\\h*)*\\|").do({arg match;
if(match[1].contains("time"), {
var repString = "", drop = 10, sig = "";
case
{match[1].contains("time 1/4")} {repString = "r4 | "}
{match[1].contains("time 2/4")} {repString = "r2 | "}
{match[1].contains("time 3/4")} {repString = "r2. | "}
{match[1].contains("time 4/4")} {repString = "r1 | "}
{match[1].contains("time 5/4")} {repString = "r2 r2. | "}
{match[1].contains("time 6/4")} {repString = "r1. | "}
{match[1].contains("time 7/4")} {repString = "r1 r2. | "}
{match[1].contains("time 8/4")} {repString = "r1 r1 | "}
{match[1].contains("time 9/4")} {repString = "r2. r2. r2. | "}
{match[1].contains("time 10/4")} {repString = "r1 r1 r2 | "}
//{match[1].contains("time 11/4")} {repString = "r1 r1 r2. | "}
{match[1].contains("time 3/8")} {repString = "r4. | "}
{match[1].contains("time 5/8")} {repString = "r4. r4 | "}
{match[1].contains("time 7/8")} {repString = "r2 r4. | "}
{match[1].contains("time 9/8")} {repString = "r4. r4. r4.| "};
if(match[1].contains("10/4") || match[1].contains("11/4"), {drop = 11});
if(match[1].findRegexp("\\d/\\d %}").size > 0, {drop = drop + 3});
if(match[1].findRegexp("\\d\\d/\\d %}").size > 0, {drop = drop + 1});
//if(match[1].contains("11"), {
// [match[1], match[1].drop(drop), repString].postln;
//});
lilyString = lilyString.replace(match[1].drop(drop), " \\hideNotes " ++ repString ++ " \\unHideNotes ")
//sig = match[1].findRegexp("\\d/\\d")[0][1];
//sig.postln;
//lilyString = lilyString.replace(match[1].drop(drop), (" R1*" ++ sig ++ " | ").postln)
})
});
//lilyString = lilyString.replace("upp ", "^\\markup{\\bold{\\larger{↑}}}").replace("down", "^\\markup{\\bold{\\larger{↓}}}");
lilyString = lilyString.replace("upp ", "").replace("down", "");
lilyString = lilyString.replace("\\note #\"4\" #1 \\normal-text \" ≈ 60\"", "\\note {4} #1 \\normal-text \" ≈ 60\"");
//write file
lilyString = lilyString ++ "\\bar \"|.\"\n}";
lilyFile.write(lilyString);
lilyFile.close;
});
};
~ammannTranscribe.value(~ammannMusic)
)
Loading…
Cancel
Save