\documentclass[../book.tex]{subfiles}
\graphicspath{{\subfix{.}}}
\begin{document}

\chapter{Plotting Multiple Data Sets}
\label{02ManyPlots}

\setcounter{section}{-1}  % Start subsections from 0

\input{prereqs/02ManyPlots_prereqs}

\newpage
\section{Problem}
\setcounter{subsection}{-1}  % Start subsections from 0

Now that you have plotted the spectrum for the final p$H$ point, you realize you have 19 other spectra that you want to add to this plot. If all of the data were in a single \cite{csv} file, you can see how you might do this. However, you have 20 different csv files---one for each spectra. You could, of course, create a common csv and copy/paste all of the data into a single csv, but you think there must be a better way.  You ask \first{}, who says "Of course! We can just go through each file one by one, and build a plot one spectrum at a time. You already know almost everything you need to do it anyway! Let's get started!"

\section{Solution}
\setcounter{subsection}{-1}  % Start subsections from 0

\subsection{Planning}
Once again, you start a rough outline and sketch of what you want to do:
\begin{lstlisting}
# gather the locations of the data to plot

# for each data file...

    # read the data and put it into Numpy arrays

    # add the data to a Plotly figure as a line trace

# arrange and format the Plotly figure

# save and show the Plotly figure
\end{lstlisting}

\First says this looks a lot like what you did for a single plot, except that, instead of a single file and a single line on your plot you want to identify a set of files and then \textit{for} each of these files, you want to add it to the plot you have. Once all the data has been added to your plot, you can format it, and then display and save it. 

``You might be thinking about this as if you had a list of files, and then \textit{for} each file in this list you added a trace to your plot.  Well... you would be right, because that is exactly what we are going to do!" \First explains that Python has a type of data type called a \lstinline{list} and also a \textbf{control structure} called \lstinline{for}, which can be used to \ul{iterate} through these items. ``We can look at these two new ideas, as well as several others, and then we will be ready to create the solution to this workflow problem."





% Lists
\subsection{Making ordered collections of data more flexible using list objects}
\label{Making_ordered_collections_of_data_more_flexible_using_list_objects}

``A Python \cite{list} is a \cite{data_type} that holds several values.  It is kind of like the \cite{Numpy_array}s that we have been using, with some advantages and disadvantages. The advantage is that lists are a bit more flexible.  A single list can simultaneously hold numbers, letters, and even even things like Plotly \cite{figure_object}s, while the default behavior for a Numpy array requires all the data to be of the same data type. However, the disadvantage of the list is that it is much less convenient to do math with them than with Numpy arrays. For instance, you make a list by enclosing elements, separated by commas, between square brackets, like this:"\footnote{Now you know that, in past chapters, when we were making Numpy arrays, we were really making lists and then converting them to arrays using the \lstinline{numpy.array()} function.}
\begin{pyin}
lst = [2, 3, 5]
\end{pyin}
\noindent``and then you try to multiply all the elements by 2, you will get a different result than if it were a Numpy array:"
\begin{pyin}
lst*2
\end{pyin}
\begin{pyout}
[2, 3, 5, 2, 3, 5]
\end{pyout}
``So you can see that the command actually just results in repeating the list elements... making a list that is twice as long."\footnote{When used in this way, the `\lstinline{*}' is called the `repetition operator.'}

``This is one way to create longer lists, but it is not very flexible, since we just repeat the list. We can grow lists by adding arbitrary elements one of two ways: \cite{concatenation} and the \lstinline{append()} \cite{method} of list objects. 



\subsection{Combining lists by concatenation}
\label{Combining_lists_by_concatenation}

``Another difference between a \cite{list} and a \cite{Numpy_array}s is that we can \cite{concatenate} lists, which is just a fancy way to say that we can add one list to the end of another. Imagine we had a second list:"
\begin{pyin}
lst2 = [2.0, "yo", True]
\end{pyin}
``We could add this list to our old list using the "+" \cite{operator}.  When this operator is between two lists, it adds the second list to the end of the first one."
\begin{pyin}
lst + lst2
\end{pyin}
\begin{pyout}
[2, 3, 5, 2.0, "yo", True]
\end{pyout}
``And so this is one way that we grow a list.\footnote{The reason we couldn't do this with Numpy arrays, is that the `+' operator will be interpreted as mathematical addition, rather than concatenation.} We can only do this with two lists. For instance the following results in an error:"
\begin{pyin}
lst + 7
\end{pyin}
``because "7" is not a list. If we wanted to simply add the 7 to the end of the list, we could do:"
\begin{pyin}
lst + [7]
\end{pyin}
``which will work, because now both items are lists. Since we did not assign the result of this concatenation to a \cite{variable}, the value of \lstinline{lst} did not change:"
\begin{pyin}
lst
\end{pyin}
\begin{pyout}
[2, 3, 5]
\end{pyout}




\subsection{Adding items to lists using the \texttt{append()} method}
\label{Adding_items_to_lists_using_the_append_method}

``There will be times that you don't wish to convert an \cite{object} to a \cite{list}, in order to add it to an existing list, and for this we can use the \lstinline{append()} \cite{method} of list objects. This method accepts a single \cite{positional_argument}, and then adds that object to the end of the list. For instance, if we wanted to add the number 10 to \lstinline{lst2,} we could use:"
\begin{pyin}
lst2.append(10)
\end{pyin}
And now 10 will appear at the end of this list:
\begin{pyin}
lst2
\end{pyin}
\begin{pyout}
[2.0, "yo", True, 10]
\end{pyout}
``Look back at this example, and you will see that in the first expression, we used \lstinline{append()} and did not assign the results to a variable. And, yet, when we ask for the value of the list, 10 was present!  This is because \lstinline{append()} modifies the list \cite{in_place}, meaning that the list we used the method on is modified directly."


``One important difference between \cite{concatenation} and \lstinline{append()} is that if the object added using \lstinline{append()} is a list, the list will be added as a list element.  Above, we use \lstinline{[7]} for concatenate, which added \lstinline{7} to the end of the list.  If we do this with \lstinline{append()}, we get \lstinline{[7]} added to the end,"
\begin{pyin}
lst2.append([7])
\end{pyin}
\begin{pyin}
lst2
\end{pyin}
\begin{pyout}
[2.0, "yo", True, 10, [7]]
\end{pyout}
``and the last item of this list is itself a list. Thus, the original list contains another list. This highlights another reason to use append instead of concatenate, when you want to add a list as a list to another list."



\subsection{Determining the number of items in a collection using the \lstinline{len()} function}
\label{Determining_the_number_of_items_in_a_collection_using_the_len_function}

``We can always find out how many items are in our lists, using the function \lstinline{len()} \cite{function}.  This also applies to other \cite{collection}s, so you can use it to get the length of \cite{Numpy_array}s as well."
\begin{pyin}
len(lst2)
\end{pyin}
\begin{pyout}
5
\end{pyout}

%
% Indicies
%
\subsection{Accessing items in lists, arrays, or strings by indexing}
\label{Access_items_in_lists,_arrays,_or_strings_by_indexing}

``Something that both a \cite{list}, a \cite{string}, and a \cite{Numpy_array} have in common is that an item in the collection can be identified and accessed by its position.  The position is given by an integer number, the so-called \cite{index}, in which the first item has the index 0, the next 1, and so on.  We can get the value at any index by using the name of the variable followed by \lstinline{[<index>]}. So, if we go back our list we assigned to \lstinline{lst}, we can get the \textit{second} element using:"
\begin{pyin}
lst[1]
\end{pyin}
\begin{pyout}
3
\end{pyout}
``We get the \textit{second} element, \textit{because index counting starts at 0 in Python}."\footnote{This is the reason the chapters, subsections, exercises, etc. in this book start counting at 0. It is a gentle reminder you should be doing the same.}

``We can also count from the back of the list forward, and in this case, the last item of the list is given the index -1, the second to last is given the index -2, and so on. So if I wanted to get the last item of our list, I can use:"
\begin{pyin}
lst[-1]
\end{pyin}
\begin{pyout}
5
\end{pyout}
``The ability to count backwards is very convenient as it allows us to access the last element in any list, without needing to know how long the list is."

``You can also modify elements of a list or Numpy array by indexing them on the left hand side of the assignment \cite{operator} (=):"
\begin{pyin}
lst[1] = 1
\end{pyin}
\begin{pyin}
lst
\end{pyin}
\begin{pyout}
[2, 1, 5]
\end{pyout}
``Indexing also works for arrays,"
\begin{pyin}
array1 = np.array([3, 4, 5])
\end{pyin}
\begin{pyin}
array1[1]    
\end{pyin}
\begin{pyout}
4
\end{pyout}
``And because arrays can contain arrays and lists can contain lists, we can use one index after another to select elements within nested arrays. Consider this 2D array:"
\begin{pyin}
array2d = np.array([array1, array1*10])
\end{pyin}

\noindent ``which looks like:"

\begin{pyin}
array2d
\end{pyin}
\begin{multiout}
array([[ 3,  4,  5],
       [30, 40, 50]])
\end{multiout}
``And then if we wanted to select the number 50, we can use:"

\begin{pyin}
array2d[1][2]
\end{pyin}
\begin{pyout}
50
\end{pyout}
\noindent ``The first index selected the \cite{inner_array}, and the second index selected the 3rd element from that second inner array."

``Finally, we can also index strings:"
\begin{pyin}
greeting = "Hiya there!"
\end{pyin}
\begin{pyin}
greeting[1]
\end{pyin}
\begin{pyout}
'i'
\end{pyout}
``There are other types of collections where we can use indices to access objects, but these three are going to be all we need to know about for most chemistry problems.  In general, you can use indices with any data type that is \cite{slicable}.  But this begs the question: what is slicing?"

%
% Slicing
%
\subsection{Access subsets of lists, arrays, or strings by slicing}
\label{Access_subsets_of_lists,_arrays,_or_strings_by_slicing}

``Any data type that you can use \acite{indices} with can be \cite{slice}d.  Slicing uses indices in order to select a range of items as well. This is done by indexing with \lstinline{[<start index>:stop index>]}. This is known as \textbf{slicing} and it will return a new list of all items in order spanning from the one at the start index (\cite{inclusive}) up to but not including the last one (\cite{exclusive}). To illustrate this, imagine we sliced our \lstinline{lst}:"
\begin{pyin}
lst[0:2]
\end{pyin}
\begin{pyout}
[2, 1]
\end{pyout}
``You can see that we got the first item (index 0) through the second (index 1) because the first index is inclusive (we get the item at that index) and the second is exclusive (we do not get the item at that index, but the one before it)."\footnote{Though it might seem strange to have the first index be inclusive and the second one exclusive, it makes it much simpler to do things like know how long the slice is, since you just subtract the first index from the last.} 

``If you leave the first index blank, then slicing will start at the first item.  If you leave the second index blank, slicing will go all the way to the end of the list. Using the slices this way, we can do:"
\begin{pyin}
greeting[:2]
\end{pyin}
\begin{pyout}
'Hi'
\end{pyout}
``Much like indexing, you can replace a slice of a list or Numpy array by assigning the slice to an equal-length list or array:"
\begin{pyin}
lst[1:] = [12, 'bye']
\end{pyin}
\begin{pyin}
lst
\end{pyin}
\begin{pyout}
[2, 12, 'bye']
\end{pyout}

``There is an important subtlety to remember: in the background, slicing lists and Numpy arrays works quite differently.  When you slice a list and assign the result to a new variable, you get a new copy of the sliced data from the old list.  Changes to that copy do not change the origninal list.  However, for a Numpy array, slicing actually creates a ``view," which is a reference to a subset of the original list.  The idea is that you are only looking at part of the array.  Because of this, changes to the view result in changes to the original array at the same time.  This can cause problems when you're not expecting it!"

%sorting
\subsection{Ordering lists and arrays by sorting}
\label{Ordering_lists_and_arrays_by_sorting}

``There are times that we won't care what order our \cite{list}s are in, and there are times we will. For instance, it is common to want lists of numbers in ascending order, or names in alphabetical order. We can accomplish this by using the \lstinline{sorted()} \cite{function}, and supply the list we want sorted as a \cite{positional_argument}. This function will \cite{return} the sorted list."

\begin{pyin}
numbers = [5, 8, 1, 5]
\end{pyin}
\begin{pyin}
sorted(numbers)
\end{pyin}
\begin{pyout}
[1, 5, 5, 8]
\end{pyout}

\begin{pyin}
names = ["Krewald", "Aronsen", "Hukka", "White"]
\end{pyin}
\begin{pyin}
sorted(names)
\end{pyin}
\begin{pyout}
["Aronsen", "Hukka", "Krewald", "White"]
\end{pyout}



%quickOpenFilenames
\subsection{Obtaining a list of paths using \texttt{codechembook.quickTools.quickOpenFilenames()}}
\label{Obtaining_a_list_of_paths_using_codechembook.quickTools.quickOpenFilenames}

``Before, we introduced the idea that we could use \lstinline{codechembook.quickTools.quickOpenFilename()} to get the \cite{path} associated with a single file. Now we will need to get the path to multiple files all at once. For this, we use \lstinline{codechembook.quickTools.quickOpenFilenames()}.  Note, this new function has an `s' at the end. It will allow you to select multiple files in a file browser, and then the function will return a \cite{list} that contains absolute paths to all of the files you selected. Go ahead and try this by entering the following in a Python console.''
\begin{pyin}
from codechembook.quickTools import quickOpenFilenames
\end{pyin}
\begin{pyin}
quickOpenFilenames()
\end{pyin}

``If you then select multiple files, you will see an output that is the paths to these files, contained within a list. Because they are in a list, we could then choose to use any functionality that we know for lists to access the path objects, such as using \cite{index}ing and \acite{slicing}."


% dictionaries
\subsection{Creating collections of objects with customized organization using dictionaries}
\label{Creating_collections_of_objects_with_customized_organization_using_dictionaries}

``There is one more \cite{data_type} we will need to introduce, which is a \cite{dictionary}.\footnote{The reason we are worrying about this is that we will need to use dictionaries to format certain aspects of Plotly figures. For now, the above is all you really need to know, and we will develop the idea of dictionaries more in the next chapter.}  We will not need much of their capabilities to solve this workflow problem, so we will only introduce the concept. A dictionary is also a \cite{collection} of elements.  However, each element in the collection is actually two parts: a \cite{key} and a \cite{value}.  Thus, when adding items to a dictionary, we need to specify a key/value pair. There are two ways to make a dictionary.  The first is to use the form <key>:<value>, with each pair separated by commas, and all the pairs placed between curly brackets (\{\}).  An example is:"
\begin{pyin}
dict1 = {"first" : 1, "second": "two", "third" : 3}
\end{pyin}
``In this usage, the key must be specified using a string.''

``The second is to use \lstinline{dict()}, and then to place keys and values separated by the assignment operator.\footnote{In this book, we will use the second way most of the time.}  An example is:"
\begin{pyin}
dict2 = dict(fourth = "four", fifth = 5, sixth = "six")
\end{pyin}
``In this approach, you do not need to use strings for the keys, but what you use must be something that can be converted to a string, which the \lstinline{dict()} function will do.''




% You can access the values of a dictionary by using the name of the dictionary and then placing the key for the value of interest between square brackets. This looks a bit like using indices, but a key is used instead of an \cite{index}.

% \begin{pyin}
% dict1["first"]
% \end{pyin}
% \begin{pyout}
% 1
% \end{pyout}

% \begin{pyin}
% dict2["sixth"]
% \end{pyin}
% \begin{pyout}
% "six"
% \end{pyout}

% Dictionaries have a lot of utility, but we will not need most of it for the code in this chapter.  We only mention dictionaries, so that you know they exist, and you can understand the \lstinline{dict()} construction. 


% Attributes
\subsection{Accessing information about objects using attributes}
\label{Accessing_information_about_objects_using_attributes}

``You already know about \cite{method}s, which we said were \cite{function}s that could be called using an \cite{object} that was an instance of a \cite{class} to which the function belongs, using <object>.<method()>.\footnote{You can review Section \ref{Exploiting_built-in_methods_to_manipulate_data_stored_in_objects}.} There is another construction that looks very similar, except that the name after \lstinline{<object>.} is \textit{not} a function.  This is indicated by the fact that there are no parentheses used.  In this case, we call this an \cite{attribute} of the object.  An attribute is essentially a \cite{variable} that lives inside of the object---it stores data and has a name, but only after the object has been created.  For instance, the \acite{Path} object in the \lstinline{pathlib} \cite{library} has several useful attributes. To access then, we first need to import \lstinline{Path} from pathlib:"
\begin{pyin}
from pathlib import Path 
\end{pyin}
``Then we can supply a path and assign it to a variable."
\begin{pyin}
myPath = Path("/<folder1>/<folder2>/<file>.csv")
\end{pyin}

``Now that we have the path, we have access to a lot of information about it simply by using attributes:
\begin{itemize}
    \item We can access the paths \textit{up to, but not including,} the file using: \lstinline{myPath.parent}, which would result in:
\lstinline{/<folder1>/<folder2>}

\item   We can access the full name, including extension using: \lstinline{myPath.name} which results in: \lstinline{<file>.csv}

\item We can get the file name, \textit{without the extension} using: \lstinline{myPath.stem}, which would result in: \lstinline{<file>}

\item We can get only the extension using: \lstinline{myPath.suffix}, which would result in: \lstinline{csv}

\end{itemize}
These examples used attributes of the Path object: \lstinline{parent}, \lstinline{name}, \lstinline{stem}, and \lstinline{suffix}, which returned the containing folders, the complete file name (including extension), the filename without an extension, and the extension only, respectively."





\subsection{Performing repetitive operations using \texttt{for} loops}
\label{Performing_repetitive_operations_using_for_loops}

``Earlier, we said that we are going to get a \cite{list} of files and then go through each one, one at a time.  There are many ways to do this in Python, but we will use the \citett{for} \cite{loop}, which is a kind of \cite{control_structure}.\footnote{You can read more about control structures in technical Chapter \ref{FlowControl}.}  The \lstinline{for} loop allows us to run the same set of lines of code over and over a set number of times.  Each time the loop code runs is called an \cite{iteration}.  To see how this will work on a list, let us just make a \lstinline{for} loop."
\begin{lstlisting}
lst = [2, 3, "hi"]
for thing in lst:
    new = [thing] + ["!"]
    print(new)
print(lst)
\end{lstlisting}
``Here, \citett{in} is a keyword that tells Python to expect the iterable collection of which we will loop through the elements.  Running this code will output the following to the console:"
\begin{multiout}
[2, '!']
[3, '!']
['hi', '!']
[2, 3, 'hi']
\end{multiout}
``What happened was: Python went through each item in our list in turn.  We assigned the item to the \cite{variable} named '\lstinline{thing}.' Then, we added this variable to a list, and \cite{concatenate}d it with another list, ['!'], assigned the result of the concatenation to a new variable, and then printed the value of this new variable. Each iteration, we go to a new item in the original list and assign it to the variable named 'thing.' So, we get the results for each list item in turn. We also printed the \lstinline{lst} at the end, and see that it is unaltered by its use in the \lstinline{for} loop, because we did nothing to change what the elements were."

\First takes a breath.  ``That was a lot, but there are a few important things to remember about the \lstinline{for} loop:
\begin{itemize}
    \item We start the loop with a line ending in a ":" character.  This will be the same for other control structures in Python, like a function definition. 
    \item We go through the entire list, one at a time.  If we wanted to use only part of the list, we could \cite{slice} it.
    \item The lines of code that happen in each iteration of the \lstinline{for} loop are indented.  So, the concatenation and the first \lstinline{print()} \cite{statement} both happen for each item. The indentation indicates they are part of the same control structure---a construction called using \cite{white_space}. We saw a similar usage when we wrote a function in Section \ref{Avoiding_repetitive_typing_by_making_your_own_functions}.
    \item We end the \lstinline{for} loop by ending the indentation. So the last \lstinline{print()} statement, which is not indented, runs after the \lstinline{or} loop completes."
\end{itemize}





\medskip
\First smiles at you, and says, "We are now in a place to solve your problem, so lets do it!''  You both sketch out the plan:
\begin{figure}[H]
    \centering
    \includegraphics[]{ChapNarrative/02ManyPlots/Figures/FlowChartCh3.pdf}
    \caption{Flowchart of the solution to plotting multiple series of data on single plot. This uses the concept of a \citett{for} \cite{loop} to \cite{iterate} through the different series. }
\end{figure}

\section{Code}
\label{ManyPlot:Code}
\setcounter{subsection}{-1}  % Start subsections from 0

% Insert code
\lstinputlisting[language=Python]{../../Distribution/Code by Chapter/Ch03 - Plotting Multiple Data Series/PlotTitrationSpectra.py}

You run this code and a file selection dialog box opens.  You use it to select all of the files in the directory 'Research/Catalyst/Titration/UVvis' and click Open, and the code quickly produces the following output in the Spyder IDE's plot window:

\vspace{-1em}
\begin{figure}[H]
    \centering
    \includegraphics[width = 5in]{./Figures/titration.png}
    \caption{Multiple spectra plotted on a single plot. In this chapter you learned to do this in a single code by looping, and how to format the appearance of the plot.}
    \label{fig:ManyPlots:Spectra}
\end{figure}

\vspace{-1em}
Your advisor happens to walk by when you are have the `browser' version of the figure up, and sees you interacting with it. He comments how cool that is, and you offer to send him the Python script. The manner in which he cocks his eyebrows tells you this is not going to happen.

\First leans over and stage whispers, ``You can have Python save the figure as HTML as well. If you send him that file, he can interact with it, just like you are!''

Sure enough, you find that introducing the line \lstinline{titration_series.write_image('titration.html')} produces an HTML file that can be shared and is an interactive plot of your data.  So cool!

\vspace{3em}
\subsection{Line-by-line explanation}
\begin{footnotesize}
\textbf{Lines}: \textbf{Explanation}
\begin{itemize}
    \item [1-6:] As always, we start with a multi line comment that has information about the script.
    
    \item [7--9:] We \cite{import} the \acite{libraries} we want to use. The only new import here is \lstinline{quickOpenFilenames}. Last chapter we used \lstinline{quickOpenFileName} (note the difference in the `s' at the end). The \cite{function} we use this chapter works the same as the function from the last chapter, with the only difference that it allows the user to select multiple files, and returns a \cite{list} of the paths associated with the files.

    \item [13:] Using the \lstinline{quickOpenFilenames()} function, we get a list of the paths to the files holding the data we wish to plot and assign them to the variable \lstinline{data_files}.  Since these files are going to all be \cite{csv} files, we also use an optional \cite{keyword_argument} in the function \cite{call}. This keyword, \lstinline{filetypes}, accepts a \cite{string}, which should have two bits of text, separated by a comma. This text is used by the native file dialog.  The first is included at text in the file explorer, as a hint for the types of files you are looking for.  The second provides a pattern that the files must match.  Here, we use `*', which is a \cite{wildcard}, followed by `csv'. This means that the native file explore will allow the user to select any files ending in 'csv', but also that only such files can be selected.  This can be useful to use when you are going to look in folders that have lots of different kinds of files, as it simplifies the choices for the user. 

    \item [14:] It would be nice to have the files in the order of the titration equivalents. %We don't have great control over the order in which the \lstinline{glob} generator function \cite{return}s names, 
    We can't assume that the files will be in the order they appear in the file dialog, however, we have named the files such that we could sort them in order of increasing number.  We can accomplish this using the \lstinline{sorted()} \cite{function}, providing the list of paths as the argument. We assign the returned sorted list to a new \cite{variable}, \lstinline{sorted_data_files}. 

    \item [17:] We are going to add our data to a single figure, and so we make a new Figure object using the \lstinline{make_subplots()} function, assigning to the variable \lstinline{titration_series}.

    \item [20--28:] We start a \citett{for} \cite{loop}, in which we iterate through the files in our \lstinline{sorted_data_files} list and add traces built from them to our figure.  We use the variable \lstinline{file} as the variable for the items returned from our \lstinline{sorted_data_files} list within the \lstinline{for} loop.
    \begin{itemize}
        \item [22\&23:] We use \lstinline{np.genfromtxt()} to read the data from our files. We set the delimiter as `\lstinline{,}', tell it to skip the first row (which is a \cite{header}), and set the keyword argument \lstinline{unpack} to \lstinline{True}, meaning that we will get data by columns. Each file is two columns of data, and so we can \cite{unpack} the value returned by \lstinline{np.genfromtxt()} to two variables.  

        \item [26--28:]  Once we have our data we use the \lstinline{add_scatter()} method of the Plotly \cite{figure_object}, \lstinline{titration_series}, to create a trace and add it to the figure. We start by specifying the $x$ and $y$ data, before other \cite{keyword}s, as explained next.
        \begin{itemize}
                \item [27:] Because there are so many closely spaced points, Plotly will default to producing a line (rather than using markers).  Here we specify the formatting of this line, using the keyword argument \lstinline{line} and supplying it within a \cite{dictionary}.  In this dictionary, we specify the color and width of the line, using these words as \cite{key}s, and providing a named color (gray), a line width (thickness) in pixels, and a dash style (`dot'). 

            \item [28:] We use the \lstinline{name} keyword argument to specify the text that will be used to label the data traces. If a legend is shown, this will be included in the legend.  However, even if there is no legend, these names will appear when hovering over the traces in an interactive plot (like when rendered in the browser). The name we use is the stem \cite{attribute} of the Path object associated with the file we are plotting data from. This is a \cite{string} that is the name of the file, without the file \cite{extension}.  Because of the naming we used for the files, this is the same as the equivalents we added and for this reason, we \cite{concatenate} the stem with the string ` eqs'. \\            
            Setting the keyword \lstinline{showlegend} to \lstinline{False}, we tell Plotly that we should not include this trace (and its name) in the figure legend. It will still appear when hovering over traces in interactive mode.\\
            The closing parentheses of this line ends the \lstinline{add_scatter()} function call, and this is the last command in the \lstinline{for} loop. 
        \end{itemize}
    \end{itemize}

    \item [31--33:] We take the first trace in our plot (\lstinline{selector = 0}), and then format only that trace, using the \lstinline{update_trace()} method of the Plotly Figure object. Because our filenames were in a sorted order, the first trace is the initial spectrum. Using the \lstinline{line} dictionary, we set the color to \lstinline{darkcyan} (a named color in Plotly) and make the line \lstinline{2} pixels wide, and change the dash style to be a solid line (\lstinline{solid}). We also change the keyword \lstinline{showlegend} to \lstinline{True}, which means this trace will appear in the legend, and we use the keyword \lstinline{name} to specify what the trace will be called in the legend. 

    \item [35--37:] We repeat the above process for the last trace (\lstinline{selector = -1}) using the same sort of indexing we would use for a list. This means that we are selecting the last trace we added. We also specify a different color and provide a different name for the trace. 

    \item [40:] When Plotly draws traces, it will draw them in order of index, meaning that the first trace in the list is drawn, then the second, and so on.  The traces can overlap, and make it difficult to see the traces under them. For this reason, it would be nice to draw the first and last traces last, while all the intermediate traces are drawn first. That way, we can easily see the first and last traces. We can accomplish this by changing the order of the traces in the collection that holds them. In this line, we accomplish this reordering. The traces to be drawn, in the order they will be drawn is held in a list in the .data \cite{attribute} of the Figure object. In this line of code, we access this attribute, take a \cite{slice} of the list from the second trace through the end, and then concatenate this with a slice of the same list that is only the first trace.\footnote{We could not use \lstinline{titrationSeries.data = titrationSeries.data[1:] + titrationSeries[0]}.  The reason  being that \lstinline{titrationSeries[0]} returns the \textit{item} from the list, but concatenation happens between two \textit{lists}.  So we need a slice for both things we concatenate.}  We then assign this concatenated list back to the data list.  This has the effect of moving what was the first plot in the list to the last position.  It will now be plotted last. This will ensure it is easy to see in the final figure. 

    \item [43:] Using the \lstinline{update_layout()} method of the Plotly Figure object, we specify the template we wish to use. 

    \item [44\&45:] Using the \lstinline{update_xaxes()} and \lstinline{update_yaxes()} methods of the Figure object, we can format the axes.  In this case, we simply add titles to the axes. 

    \item [46:] We show the final figure using '\lstinline{png+browser}', which opens up a interactive plot in a web browser and outputs to the Spyder plot window (if you are using the Spyder IDE). 

    \item [47:] We save the Plotly figure to an image file, providing Path and a size to save it as. We also use two keyword arguments for the \lstinline{write_image} method:  \lstinline{width} and \lstinline{height}, which are used to specify the width and height of the figure. The units are in pixels, and so the numbers must be able to be written as whole numbers.  Here, when we scale 3.3 and 4.3 by 100, to give 33 and 43, respectively. If you then produced this figure, and scaled it to 3.3 and 4.3 inches, it would be drawn at a resolution of 300 pixels per inch. This is a fine resolution for print and web, though some print applications might desire higher resolution, such as 600 pixels per inch.
    
    When looking at how the image is saved, we take one of the \lstinline{Path} objects from our list of sorted file names, and then use the \lstinline{parent} attribute of the object to get the folder that the file was in.  We then supply a filename. The end result is that we save the figure output to the same folder as our data came from. Now, even though there is a .png file in this folder. 

\end{itemize}
\end{footnotesize}

\hrule
\input{Exercises/Chapter 03 Plotting multiple data series at once}
\hrule

\end{document}
