Skip to content

Commit

Permalink
Merge branch 'master' into textsize
Browse files Browse the repository at this point in the history
  • Loading branch information
mlwright84 committed Aug 4, 2017
2 parents 70b445b + 6ce3c9a commit 63b5b16
Show file tree
Hide file tree
Showing 21 changed files with 281 additions and 143 deletions.
46 changes: 45 additions & 1 deletion README.md
Expand Up @@ -19,7 +19,7 @@ Before starting to build RIVET, you will need to have the following installed:
* Qt 5 * Qt 5
* Boost (including boost serialization; version 1.60 or newer required) * Boost (including boost serialization; version 1.60 or newer required)


Below we give step-by-step instructions for installing these required dependencies and building RIVET on Ubuntu and Mac OS X. Currently, use of RIVET in Windows is not supported; we are working on this. Below we give step-by-step instructions for installing these required dependencies and building RIVET on Ubuntu and Mac OS X. Building RIVET on Windows is not yet supported (we are working on this), but it is possible to build RIVET using the Bash shell on Windows 10.


## Building On Ubuntu ## Building On Ubuntu


Expand Down Expand Up @@ -135,6 +135,50 @@ To solve the problem, try running:


sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer


## Building in the Bash Shell on Windows 10

First, ensure that you have the [Windows 10 Creators Update](https://support.microsoft.com/en-us/instantanswers/d4efb316-79f0-1aa1-9ef3-dcada78f3fa0/get-the-windows-10-creators-update). Then activate the [Windows 10 Bash Shell](https://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/). This will provide a Bash shell with Ubuntu 16.04 inside of Windows 10.

Open the Bash shell and install dependencies. Use the following command to install cmake, a compiler, and Qt5:

sudo apt-get install cmake build-essential qt5-default qt5-qmake qtbase5-dev-tools

The Ubuntu 16.04 repositories include Boost 1.58, but RIVET requires Boost 1.60 or newer. The following instructions install Boost 1.64 into `/usr/local/boost_1_64_0/`:

1. Download a compressed Boost file into your home directory:

cd ~
wget "https://dl.bintray.com/boostorg/release/1.64.0/source/boost_1_64_0.tar.bz2"

2. Unpack Boost to `/usr/local/`:

cd /usr/local
sudo tar xvjf ~/boost_1_64_0.tar.bz2
cd boost_1_64_0

3. Setup Boost:

sudo ./boostrap.sh --prefix=/usr/local
sudo ./b2
sudo ./b2 install

4. Return to home directory and delete the compressed Boost file.

cd ~
rm boost_1_64_0.tar.bz2

In order to use the RIVET viewer, you must install an X server such as [Xming](https://sourceforge.net/projects/xming/).

It is also necessary to set two environment variables, as follows:

export LD_LIBRARY_PATH=/usr/local/boost_1_64_0/stage/lib/:$LD_LIBRARY_PATH
export DISPLAY=:0

These environment variables will be reset when you close the Bash shell. To avoid having to run the two lines above when you reopen the shell, add these lines to the end of the file `~/.bashrc`.

You are now ready to build RIVET. Follow the instructions in the section of this readme under the heading [Building on Ubuntu: Building RIVET](https://github.com/rivetTDA/rivet/#building-rivet).


## Contributing ## Contributing


We welcome your contribution! Code, documentation, unit tests, We welcome your contribution! Code, documentation, unit tests,
Expand Down
1 change: 1 addition & 0 deletions computation.cpp
Expand Up @@ -54,6 +54,7 @@ std::unique_ptr<ComputationResult> Computation::compute_raw(ComputationInput& in
} }
} }
} }

//STAGE 3: COMPUTE MULTIGRADED BETTI NUMBERS //STAGE 3: COMPUTE MULTIGRADED BETTI NUMBERS


std::unique_ptr<ComputationResult> result(new ComputationResult); std::unique_ptr<ComputationResult> result(new ComputationResult);
Expand Down
83 changes: 54 additions & 29 deletions console.cpp
Expand Up @@ -50,6 +50,7 @@ static const char USAGE[] =
rivet_console --version rivet_console --version
rivet_console <input_file> --identify rivet_console <input_file> --identify
rivet_console <input_file> --betti [-H <dimension>] [-V <verbosity>] [-x <xbins>] [-y <ybins>] rivet_console <input_file> --betti [-H <dimension>] [-V <verbosity>] [-x <xbins>] [-y <ybins>]
rivet_console <input_file> <output_file> --betti [-H <dimension>] [-V <verbosity>] [-x <xbins>] [-y <ybins>]
rivet_console <precomputed_file> --bounds rivet_console <precomputed_file> --bounds
rivet_console <precomputed_file> --barcodes <line_file> rivet_console <precomputed_file> --barcodes <line_file>
rivet_console <input_file> <output_file> [-H <dimension>] [-V <verbosity>] [-x <xbins>] [-y <ybins>] [-f <format>] [--binary] rivet_console <input_file> <output_file> [-H <dimension>] [-V <verbosity>] [-x <xbins>] [-y <ybins>] [-f <format>] [--binary]
Expand All @@ -71,10 +72,10 @@ static const char USAGE[] =
-b --betti Print dimension and Betti number information, then exit. -b --betti Print dimension and Betti number information, then exit.
--bounds Print lower and upper bounds for the module in <precomputed_file> and exit --bounds Print lower and upper bounds for the module in <precomputed_file> and exit
--barcodes <line_file> Print barcodes for the line queries in line_file, then exit. --barcodes <line_file> Print barcodes for the line queries in line_file, then exit.
line_file consists of pairs "m b", each representing a query line. line_file consists of pairs "m o", each representing a query line.
m is the slope of the query line, given in degrees (0 to 90); b is the m is the slope of the query line, given in degrees (0 to 90); o is the
signed distance from the query line to the origin, where the sign is signed distance from the query line to the origin, where the sign is
positive if the line is below/right of the origin and negative otherwise. positive if the line is above/left of the origin and negative otherwise.
Example line_file contents: Example line_file contents:
Expand Down Expand Up @@ -125,9 +126,9 @@ void print_dims(TemplatePointsMessage const& message, std::ostream& ostream)
auto data = message.homology_dimensions.data(); auto data = message.homology_dimensions.data();
ostream << "Dimensions > 0:" << std::endl; ostream << "Dimensions > 0:" << std::endl;


for (unsigned long row = 0; row < shape[0]; row++) { for (unsigned long col = 0; col < shape[0]; col++) {
for (unsigned long col = 0; col < shape[1]; col++) { for (unsigned long row = 0; row < shape[1]; row++) {
unsigned dim = data[row * shape[0] + col]; unsigned dim = data[col * shape[1] + row];
if (dim > 0) { if (dim > 0) {
ostream << "(" << col << ", " << row << ", " << dim << ")" << std::endl; ostream << "(" << col << ", " << row << ", " << dim << ")" << std::endl;
} }
Expand Down Expand Up @@ -362,7 +363,7 @@ int main(int argc, char* argv[])
std::clog << "Wrote arrangement to " << params.outputFile << std::endl; std::clog << "Wrote arrangement to " << params.outputFile << std::endl;
} }
}); });
computation.template_points_ready.connect([&points_message, &binary, &betti_only, &verbosity](TemplatePointsMessage message) { computation.template_points_ready.connect([&points_message, &binary, &betti_only, &verbosity, &params](TemplatePointsMessage message) {
points_message.reset(new TemplatePointsMessage(message)); points_message.reset(new TemplatePointsMessage(message));


if (binary) { if (binary) {
Expand Down Expand Up @@ -397,8 +398,27 @@ int main(int argc, char* argv[])
print_dims(message, std::cout); print_dims(message, std::cout);
std::cout << std::endl; std::cout << std::endl;
print_betti(message, std::cout); print_betti(message, std::cout);
std::cout.flush();
//if an output file has been specified, then save the Betti numbers in an arrangement file (with no barcode templates)
if (!params.outputFile.empty()) {
std::ofstream file(params.outputFile);
if (file.is_open()) {
std::vector<exact> emptyvec;
std::shared_ptr<Arrangement> temp_arrangement = std::make_shared<Arrangement>(emptyvec, emptyvec, verbosity);
std::shared_ptr<ArrangementMessage> temp_am = std::make_shared<ArrangementMessage>(*temp_arrangement);
if (verbosity > 0) {
debug() << "Writing file:" << params.outputFile;
}
write_boost_file(params, *points_message, *temp_am);
} else {
std::stringstream ss;
ss << "Error: Unable to write file:" << params.outputFile;
throw std::runtime_error(ss.str());
}
}

//TODO: this seems a little abrupt... //TODO: this seems a little abrupt...
std::cout.flush();
exit(0); exit(0);
} }
}); });
Expand All @@ -413,19 +433,21 @@ int main(int argc, char* argv[])
} }
std::unique_ptr<ComputationResult> result; std::unique_ptr<ComputationResult> result;


std::unique_ptr<InputData> input;

std::shared_ptr<Arrangement> arrangement;

if (barcodes || bounds) { if (barcodes || bounds) {
result = load_from_precomputed(params.fileName); result = load_from_precomputed(params.fileName);
if (barcodes) { if (barcodes) {
if (!slices.empty()) { if (!slices.empty()) {
process_barcode_queries(slices, *result); process_barcode_queries(slices, *result);
return 0;
} }
} else { } else {
process_bounds(*result); process_bounds(*result);
} }
} else { } else {


std::unique_ptr<InputData> input;
try { try {
input = inputManager.start(progress); input = inputManager.start(progress);
} catch (const std::exception& e) { } catch (const std::exception& e) {
Expand All @@ -441,31 +463,34 @@ int main(int argc, char* argv[])
if (params.verbosity >= 2) { if (params.verbosity >= 2) {
debug() << "Computation complete; augmented arrangement ready."; debug() << "Computation complete; augmented arrangement ready.";
} }
auto arrangement = result->arrangement; arrangement = result->arrangement;
if (params.verbosity >= 4) { if (params.verbosity >= 4) {
arrangement->print_stats(); arrangement->print_stats();
} }


//if an output file has been specified, then save the arrangement }
if (!params.outputFile.empty()) { //if an output file has been specified, then save the arrangement
std::ofstream file(params.outputFile); if (!params.outputFile.empty()) {
if (file.is_open()) { std::ofstream file(params.outputFile);
if (verbosity > 0) { if (file.is_open()) {
debug() << "Writing file:" << params.outputFile; if (arrangement == nullptr) {
} arrangement.reset(new Arrangement());
if (params.outputFormat == "R0") { }
FileWriter fw(params, *input, *(arrangement), result->template_points); if (verbosity > 0) {
fw.write_augmented_arrangement(file); debug() << "Writing file:" << params.outputFile;
} else if (params.outputFormat == "R1") { }
write_boost_file(params, *points_message, *arrangement_message); if (params.outputFormat == "R0") {
} else { FileWriter fw(params, *input, *(arrangement), result->template_points);
throw std::runtime_error("Unsupported output format: " + params.outputFormat); fw.write_augmented_arrangement(file);
} } else if (params.outputFormat == "R1") {
write_boost_file(params, *points_message, *arrangement_message);
} else { } else {
std::stringstream ss; throw std::runtime_error("Unsupported output format: " + params.outputFormat);
ss << "Error: Unable to write file:" << params.outputFile;
throw std::runtime_error(ss.str());
} }
} else {
std::stringstream ss;
ss << "Error: Unable to write file:" << params.outputFile;
throw std::runtime_error(ss.str());
} }
} }
if (params.verbosity > 2) { if (params.verbosity > 2) {
Expand Down
5 changes: 5 additions & 0 deletions dcel/arrangement_message.cpp
Expand Up @@ -530,3 +530,8 @@ Arrangement ArrangementMessage::to_arrangement() const
// std::clog << "All anchors identical in to_arrangement" << std::endl; // std::clog << "All anchors identical in to_arrangement" << std::endl;
return arrangement; return arrangement;
} }

bool ArrangementMessage::is_empty() const
{
return ( x_exact.empty() && y_exact.empty() );
}
2 changes: 2 additions & 0 deletions dcel/arrangement_message.h
Expand Up @@ -51,6 +51,8 @@ class ArrangementMessage {


Arrangement to_arrangement() const; Arrangement to_arrangement() const;


bool is_empty() const;

private: private:
friend class boost::serialization::access; friend class boost::serialization::access;


Expand Down
13 changes: 13 additions & 0 deletions dcel/barcode.cpp
Expand Up @@ -65,6 +65,19 @@ void Barcode::add_bar(double b, double d, unsigned m)
bars.insert(MultiBar(b, d, m)); bars.insert(MultiBar(b, d, m));
} }


//shifts the barcode by adding amount to each endpoint of each bar
std::unique_ptr<Barcode> Barcode::shift(double amount)
{
std::unique_ptr<Barcode> bc = std::unique_ptr<Barcode>(new Barcode());

for (std::multiset<MultiBar>::iterator it = bars.begin(); it != bars.end(); ++it) {
MultiBar mb = *it;
bc->add_bar(mb.birth + amount, mb.death + amount, mb.multiplicity);
}

return bc;
}

//returns an iterator to the first bar in the barcode //returns an iterator to the first bar in the barcode
std::set<MultiBar>::const_iterator Barcode::begin() const std::set<MultiBar>::const_iterator Barcode::begin() const
{ {
Expand Down
3 changes: 3 additions & 0 deletions dcel/barcode.h
Expand Up @@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef __BARCODE_H__ #ifndef __BARCODE_H__
#define __BARCODE_H__ #define __BARCODE_H__


#include <memory>
#include <set> #include <set>


struct MultiBar { struct MultiBar {
Expand All @@ -40,6 +41,8 @@ class Barcode {


void add_bar(double b, double d, unsigned m); //adds a bar to the barcode void add_bar(double b, double d, unsigned m); //adds a bar to the barcode


std::unique_ptr<Barcode> shift(double amount); //shifts the barcode by adding amount to each endpoint of each bar

std::multiset<MultiBar>::const_iterator begin() const; //returns an iterator to the first bar in the barcode std::multiset<MultiBar>::const_iterator begin() const; //returns an iterator to the first bar in the barcode
std::multiset<MultiBar>::const_iterator end() const; //returns an iterator to the pst-the-end element the barcode std::multiset<MultiBar>::const_iterator end() const; //returns an iterator to the pst-the-end element the barcode
unsigned size() const; //returns the number of multibars in the barcode unsigned size() const; //returns the number of multibars in the barcode
Expand Down
42 changes: 26 additions & 16 deletions dcel/barcode_template.cpp
Expand Up @@ -140,7 +140,8 @@ bool operator==(BarTemplate const& left, BarTemplate const& right)
&& left.multiplicity == right.multiplicity; && left.multiplicity == right.multiplicity;
} }


//rescales a barcode template by projecting points onto the specified line //rescales a barcode template by projecting points onto the line specificed by angle and offset
// NOTE: parametrization of the line is as in the RIVET paper
// NOTE: angle in DEGREES // NOTE: angle in DEGREES
std::unique_ptr<Barcode> BarcodeTemplate::rescale(double angle, double offset, std::unique_ptr<Barcode> BarcodeTemplate::rescale(double angle, double offset,
const std::vector<TemplatePoint>& template_points, const std::vector<TemplatePoint>& template_points,
Expand Down Expand Up @@ -186,7 +187,7 @@ std::unique_ptr<Barcode> BarcodeTemplate::rescale(double angle, double offset,
} }
} }


//if the line is vertical or horizontal, we must now add the vertical bars //if the line is vertical or horizontal, we must now add the infinite bars
if (angle == 0 || angle == 90) { if (angle == 0 || angle == 90) {
for (std::map<unsigned, unsigned>::iterator it = infinite_bars.begin(); it != infinite_bars.end(); ++it) { for (std::map<unsigned, unsigned>::iterator it = infinite_bars.begin(); it != infinite_bars.end(); ++it) {
double birth = project(template_points[it->first], angle, offset, grades); double birth = project(template_points[it->first], angle, offset, grades);
Expand All @@ -197,31 +198,40 @@ std::unique_ptr<Barcode> BarcodeTemplate::rescale(double angle, double offset,
return bc; return bc;
} //end rescale_barcode_template() } //end rescale_barcode_template()


//computes the projection of an xi support point onto the specified line //computes the projection of an xi support point onto the line specificed by angle and offset
// NOTE: parametrization of the line is as in the RIVET paper
// NOTE: returns INFTY if the point has no projection (can happen only for horizontal and vertical lines) // NOTE: returns INFTY if the point has no projection (can happen only for horizontal and vertical lines)
// NOTE: angle in DEGREES // NOTE: angle in DEGREES
double BarcodeTemplate::project(const TemplatePoint& pt, double angle, double offset, const Grades& grades) double BarcodeTemplate::project(const TemplatePoint& pt, double angle, double offset, const Grades& grades)
{ {
if (angle == 0) //then line is horizontal if (angle == 0) { //then line is horizontal
{ if (grades.y[pt.y] <= offset) { //then point is below the line, so projection exists
if (grades.y[pt.y] <= offset) //then point is below the line, so projection exists
return grades.x[pt.x]; return grades.x[pt.x];
else //then no projection } //else: no projection
return rivet::numeric::INFTY; return rivet::numeric::INFTY;
} else if (angle == 90) //then line is vertical } else if (angle == 90) { //then line is vertical
{ if (grades.x[pt.x] <= -1 * offset) { //then point is left of the line, so projection exists
if (grades.x[pt.x] <= -1 * offset) //then point is left of the line, so projection exists
return grades.y[pt.y]; return grades.y[pt.y];
else //then no projection } //else: no projection
return rivet::numeric::INFTY; return rivet::numeric::INFTY;
} }

//if we get here, then line is neither horizontal nor vertical //if we get here, then line is neither horizontal nor vertical
double radians = angle * rivet::numeric::PI / 180; double radians = angle * rivet::numeric::PI / 180;
double x = grades.x[pt.x]; double x = grades.x[pt.x];
double y = grades.y[pt.y]; double y = grades.y[pt.y];


if (y > x * tan(radians) + offset / cos(radians)) //then point is above line double yL = x * tan(radians) + offset / cos(radians); // the point (x, yL) is on the line
return y / sin(radians) - offset / tan(radians); //project right
if (y >= yL) { //then point is above line, so project to the right
if (offset >= 0) {
return (y * cos(radians) - offset) / (sin(radians) * cos(radians));
} //else
return y / sin(radians);
} //else: point is below the line, so project up
if (offset >= 0) {
return x / cos(radians);
} //else
return yL / sin(radians);


return x / cos(radians) + offset * tan(radians); //project up
} //end project() } //end project()
8 changes: 5 additions & 3 deletions dcel/barcode_template.h
Expand Up @@ -59,13 +59,15 @@ class BarcodeTemplate {
std::set<BarTemplate>::iterator end(); //returns an iterator to the past-the-end element of the barcode std::set<BarTemplate>::iterator end(); //returns an iterator to the past-the-end element of the barcode
bool is_empty(); //returns true iff this barcode has no bars bool is_empty(); //returns true iff this barcode has no bars


//rescales a barcode template by projecting points onto the specified line //rescales a barcode template by projecting points onto the line specificed by angle and offset
// NOTE: angle in DEGREES // NOTE: parametrization of the line is as in the RIVET paper
// NOTE: angle in DEGREES
std::unique_ptr<Barcode> rescale(double angle, double offset, std::unique_ptr<Barcode> rescale(double angle, double offset,
const std::vector<TemplatePoint>& template_points, const std::vector<TemplatePoint>& template_points,
const Grades& grades); const Grades& grades);


//computes the projection of an xi support point onto the specified line //computes the projection of an xi support point onto the line specificed by angle and offset
// NOTE: parametrization of the line is as in the RIVET paper
// NOTE: returns INFTY if the point has no projection (can happen only for horizontal and vertical lines) // NOTE: returns INFTY if the point has no projection (can happen only for horizontal and vertical lines)
// NOTE: angle in DEGREES // NOTE: angle in DEGREES
double project(const TemplatePoint& pt, double angle, double offset, const Grades& grades); double project(const TemplatePoint& pt, double angle, double offset, const Grades& grades);
Expand Down

0 comments on commit 63b5b16

Please sign in to comment.