[redistricter] 8 new revisions pushed by brian.olson on 2013-09-02 04:11 GMT

3 views
Skip to first unread message

redist...@googlecode.com

unread,
Sep 2, 2013, 12:11:46 AM9/2/13
to redistrict...@googlegroups.com
8 new revisions:

Revision: c78afb72f760
Branch: default
Author: Brian Olson <brian...@gmail.com>
Date: Sun May 12 03:07:44 2013 UTC
Log: a bunch of const char** argv and propagation thereof. more
arghandler....
http://code.google.com/p/redistricter/source/detail?r=c78afb72f760

Revision: 8f05667c8624
Branch: default
Author: Brian Olson <brian...@gmail.com>
Date: Sat May 18 14:31:54 2013 UTC
Log: cleanup
http://code.google.com/p/redistricter/source/detail?r=8f05667c8624

Revision: cf03356a5e47
Branch: default
Author: Brian Olson <brian...@gmail.com>
Date: Sat May 25 18:19:46 2013 UTC
Log: Make drend easier to use, detecting number of districts from
loaded so...
http://code.google.com/p/redistricter/source/detail?r=cf03356a5e47

Revision: 0d6164e1f1a9
Branch: default
Author: Brian Olson <brian...@gmail.com>
Date: Sat May 25 21:24:58 2013 UTC
Log: a bunch of work on rendering 2013 actual districts for comparison
http://code.google.com/p/redistricter/source/detail?r=0d6164e1f1a9

Revision: 5cc57190fefc
Branch: default
Author: Brian Olson <brian...@gmail.com>
Date: Mon May 27 18:25:38 2013 UTC
Log: fix lazy allocator
http://code.google.com/p/redistricter/source/detail?r=5cc57190fefc

Revision: 16bdfe1329b7
Branch: default
Author: Brian Olson <brian...@gmail.com>
Date: Mon May 27 20:48:08 2013 UTC
Log: a bunch of work on new results page in django template with
current vs...
http://code.google.com/p/redistricter/source/detail?r=16bdfe1329b7

Revision: c03009c1b360
Branch: default
Author: Brian Olson <brian...@gmail.com>
Date: Mon May 20 15:23:00 2013 UTC
Log: move census 2000 results to /2000/ on website
http://code.google.com/p/redistricter/source/detail?r=c03009c1b360

Revision: dfa2a0a5229c
Branch: default
Author: Brian Olson <brian...@gmail.com>
Date: Mon May 27 21:24:51 2013 UTC
Log: hg merge
http://code.google.com/p/redistricter/source/detail?r=dfa2a0a5229c

==============================================================================
Revision: c78afb72f760
Branch: default
Author: Brian Olson <brian...@gmail.com>
Date: Sun May 12 03:07:44 2013 UTC
Log: a bunch of const char** argv and propagation thereof. more
arghandler.h
http://code.google.com/p/redistricter/source/detail?r=c78afb72f760

Added:
/arghandler_test.cpp
Modified:
/GeoData.h
/Solver.cpp
/Solver.h
/analyze.cpp
/arghandler.h
/drendmain.cpp
/fileio.cpp
/linkfixup.cpp
/makeopts/Darwin.pre
/nonguimain.cpp
/notes.txt
/rtaToDsz.cpp

=======================================
--- /dev/null
+++ /arghandler_test.cpp Sun May 12 03:07:44 2013 UTC
@@ -0,0 +1,48 @@
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "arghandler.h"
+
+const char* targv[] =
+{
+ "progname",
+ "-c=1",
+ "-d", "2",
+ "-f=4",
+ "--g=5",
+ "--e", "3"
+};
+
+int test(int argc, char** argv) {
+ int argi = 1;
+ char* c;
+ char* d;
+ char* e;
+ char* f;
+ char* g;
+
+ while (argi < argc) {
+ StringArgWithCopy("c", &c);
+ StringArgWithCopy("d", &d);
+ StringArgWithCopy("e", &e);
+ StringArgWithCopy("f", &f);
+ StringArgWithCopy("g", &g);
+ assert(0); // this should never be reached, macros should always
`continue`
+ }
+
+ assert(0 == strcmp(c, "1"));
+ assert(0 == strcmp(d, "2"));
+ assert(0 == strcmp(e, "3"));
+ assert(0 == strcmp(f, "4"));
+ assert(0 == strcmp(g, "5"));
+
+ return 0;
+}
+
+int main(int argc, char** argv) {
+
+ test(sizeof(targv)/sizeof(char*), (char**)targv);
+
+ return 0;
+}
=======================================
--- /GeoData.h Sun Apr 3 18:18:14 2011 UTC
+++ /GeoData.h Sun May 12 03:07:44 2013 UTC
@@ -93,7 +93,7 @@
}

GeoData();
- int open( char* inputname );
+ int open( const char* inputname );
virtual int load() = 0;
virtual int numDistricts();
//virtual uint64_t ubid( int index ) = 0;
@@ -177,9 +177,9 @@
};


-//GeoData* openZCTA( char* inputname );
-GeoData* openUf1( char* inputname );
-GeoData* openPlGeo( char* inputname );
-GeoData* protobufGeoDataTag( char* inputname );
+//GeoData* openZCTA( const char* inputname );
+GeoData* openUf1( const char* inputname );
+GeoData* openPlGeo( const char* inputname );
+GeoData* protobufGeoDataTag( const char* inputname );

#endif /* GEODATA_H */
=======================================
--- /Solver.cpp Sun Apr 3 18:40:31 2011 UTC
+++ /Solver.cpp Sun May 12 03:07:44 2013 UTC
@@ -156,7 +156,7 @@
}

// doesn't do anything, just a tag to switch on in Solver::load()
-GeoData* protobufGeoDataTag( char* inputname ) {
+GeoData* protobufGeoDataTag( const char* inputname ) {
assert(0);
exit(1);
return NULL;
@@ -937,14 +937,14 @@
"-runDutySeconds run for this many seconds, then sleep (10)\n"
"-sleepDutySeconds sleep for this many seconds, then run (0)\n";

-int Solver::handleArgs( int argc, char** argv ) {
+int Solver::handleArgs( int argc, const char** argv ) {
int argcout = 1;
popRatioFactor.clear();
popRatioFactor.setPoint( -1, District2::popRatioFactor );
int argi = 1;
- char* uf1InputName = NULL;
- char* plGeoInputName = NULL;
- char* pbInputName = NULL;
+ const char* uf1InputName = NULL;
+ const char* plGeoInputName = NULL;
+ const char* pbInputName = NULL;
const char* binLogName = NULL;
const char* statLogName = NULL;
bool oldCDs = false;
@@ -1062,7 +1062,7 @@
static char bestKmppPng[] = "bestKmpp.png";
#endif

-int Solver::main( int argc, char** argv ) {
+int Solver::main( int argc, const char** argv ) {
struct rusage start, sa, sb, end;
struct rusage* a = &sa;
struct rusage* b = &sb;
=======================================
--- /Solver.h Sun Apr 3 18:18:14 2011 UTC
+++ /Solver.h Sun May 12 03:07:44 2013 UTC
@@ -28,7 +28,7 @@
DistrictSet* (*districtSetFactory)(Solver*);
DistrictSet* dists;

- char* inputname;
+ const char* inputname;
int generations;
char* dumpname;
char* loadname;
@@ -61,7 +61,7 @@
#endif

GeoData* gd;
- GeoData* (*geoFact)(char*);
+ GeoData* (*geoFact)(const char*);

uint32_t numEdges;
int32_t* edgeData;
@@ -89,7 +89,7 @@
Solver();
~Solver();

- int handleArgs( int argc, char** argv );
+ int handleArgs( int argc, const char** argv );
void load();
// If filename is null, add ".links" to inputname
void readLinksFile(const char* filename);
@@ -167,7 +167,7 @@
void zoomOut();
void zoomAll();
void centerOnPoint( int index );
- int main( int argc, char** argv );
+ int main( int argc, const char** argv );

inline int setDist( POPTYPE d, int i ) {
return (*dists)[(d)].add( this, (i), (d) );
=======================================
--- /analyze.cpp Sun Apr 3 18:18:14 2011 UTC
+++ /analyze.cpp Sun May 12 03:07:44 2013 UTC
@@ -4,6 +4,8 @@
#include <unistd.h>
#include <math.h>
#include <zlib.h>
+
+#include "arghandler.h"
#include "District2.h"
#include "Bitmap.h"
#include "Node.h"
@@ -63,17 +65,32 @@
}
}

-int main( int argc, char** argv ) {
+void stringVectorAppendCallback(vector<const char*>& context, const char*
str) {
+ context.push_back(str);
+}
+
+int main( int argc, const char** argv ) {
Solver sov;
int nargc;
+
+ const char* textOutName = NULL;
+ bool notext = false;
FILE* textout = stdout;
+
+ const char* csvOutName = NULL;
+ bool nocsv = false;
FILE* csvout = NULL;
+
+ const char* htmlOutName = NULL;
+ bool nohtml = false;
FILE* htmlout = NULL;
+
int dsort = -1;
bool distrow = true;
bool distcol = false;
bool quiet = false;
bool loadSolutionCsvMode = false;
+ const char* csvInName = NULL;
const char* exportPath = NULL;

vector<const char*> compareArgs;
@@ -82,84 +99,34 @@
nargc = 1;
sov.districtSetFactory = District2SetFactory;

- for (int i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "--compare")) {
- // --compare filename:colnum,colnum,colnum
- ++i;
- compareArgs.push_back(argv[i]);
- } else if (!strcmp(argv[i], "--labels")) {
- // comma separated list of labels to match a corresponding compare set
- ++i;
- labelArgs.push_back(argv[i]);
- } else if (!strcmp(argv[i], "--dsort")) {
- // when printing districts as rows, sort by column N
- ++i;
- dsort = atoi(argv[i]);
- } else if (!strcmp(argv[i], "--html")) {
- ++i;
- if (argv[i][0] == '\0') {
- htmlout = stdout;
- quiet = true;
- } else {
- htmlout = fopen(argv[i], "w");
- if (htmlout == NULL) {
- perror(argv[i]);
- exit(1);
- }
- }
- } else if (!strcmp(argv[i], "--nohtml")) {
- htmlout = NULL;
- } else if (!strcmp(argv[i], "--text")) {
- ++i;
- if (argv[i][0] == '\0') {
- textout = stdout;
- quiet = true;
- } else {
- textout = fopen(argv[i], "w");
- if (textout == NULL) {
- perror(argv[i]);
- exit(1);
- }
- }
- } else if (!strcmp(argv[i], "--notext")) {
- textout = NULL;
- } else if (!strcmp(argv[i], "--csv")) {
- ++i;
- if (argv[i][0] == '\0') {
- csvout = stdout;
- quiet = true;
- } else {
- csvout = fopen(argv[i], "w");
- if (csvout == NULL) {
- perror(argv[i]);
- exit(1);
- }
- }
- } else if (!strcmp(argv[i], "--nocsv")) {
- csvout = NULL;
- } else if (!strcmp(argv[i], "--distrow")) {
- // print table with districts in rows
- distrow = true;
- } else if (!strcmp(argv[i], "--nodistrow")) {
- distrow = false;
- } else if (!strcmp(argv[i], "--distcol")) {
- // print table with districts in columns
- distcol = true;
- } else if (!strcmp(argv[i], "--nodistcol")) {
- distcol = false;
- } else if (!strcmp(argv[i], "--export")) {
- ++i;
- exportPath = argv[i];
- } else if (!strcmp(argv[i], "--csv-solution")) {
- ++i;
- sov.loadname = argv[i];
- loadSolutionCsvMode = true;
- } else {
- argv[nargc] = argv[i];
- nargc++;
- }
+ int argi = 1;
+ while (argi < argc) {
+ StringArgWithCallback("compare", stringVectorAppendCallback,
compareArgs);
+ StringArgWithCallback("labels", stringVectorAppendCallback,
labelArgs);
+ IntArg("dsort", &dsort);
+ StringArg("html", &htmlOutName);
+ BoolArg("nohtml", &nohtml);
+ StringArg("text", &textOutName);
+ BoolArg("notext", &notext);
+ StringArg("csv", &csvOutName);
+ BoolArg("nocsv", &nocsv);
+ BoolArg("distrow", &distrow);
+ BoolArg("distcol", &distcol);
+ StringArg("export", &exportPath);
+ StringArg("csv-solution", &csvInName);
+
+ // default:
+ argv[nargc] = argv[argi];
+ nargc++;
+ argi++;
}
argv[nargc]=NULL;
+
+ if (csvInName != NULL) {
+ sov.loadname = strdup(csvInName);
+ loadSolutionCsvMode = true;
+ }
+
int argcout = sov.handleArgs(nargc, argv);
if (argcout != 1) {
// TODO: print local usage here too
@@ -168,6 +135,52 @@
exit(1);
return 1;
}
+
+ if (notext) {
+ textout = NULL;
+ } else {
+ if ((textOutName == NULL) || (textOutName[0] == '\0') || (0 ==
strcmp("-", textOutName))) {
+ textout = stdout;
+ quiet = true;
+ } else {
+ textout = fopen(textOutName, "w");
+ if (textout == NULL) {
+ perror(textOutName);
+ exit(1);
+ }
+ }
+ }
+
+ if (nocsv || (csvOutName == NULL)) {
+ csvout = NULL;
+ } else {
+ if ((csvOutName[0] == '\0') || (0 == strcmp("-", csvOutName))) {
+ csvout = stdout;
+ quiet = true;
+ } else {
+ csvout = fopen(csvOutName, "w");
+ if (csvout == NULL) {
+ perror(csvOutName);
+ exit(1);
+ }
+ }
+ }
+
+ if (nohtml || (htmlOutName == NULL)) {
+ htmlout = NULL;
+ } else {
+ if ((htmlOutName[0] == '\0') || (0 == strcmp("-", htmlOutName))) {
+ htmlout = stdout;
+ quiet = true;
+ } else {
+ htmlout = fopen(htmlOutName, "w");
+ if (htmlout == NULL) {
+ perror(htmlOutName);
+ exit(1);
+ }
+ }
+ }
+
sov.load();
sov.initNodes();
sov.allocSolution();
=======================================
--- /arghandler.h Mon Aug 23 04:16:44 2010 UTC
+++ /arghandler.h Sun May 12 03:07:44 2013 UTC
@@ -148,11 +148,12 @@
case 1: argi++; continue; \
default: fprintf(stderr, "ICE %d\n", __LINE__); exit(1); return 1;}

-#define StringArgWithCopy(optname, value) switch(_StringArg(argc, argv,
&argi, (optname), (value))) { \
+#define StringArgWithCopy(optname, value) {const char* __cb_str_value =
NULL; switch(_StringArg(argc, argv, &argi, (optname), &__cb_str_value)) { \
case -1: fprintf(stderr, "bogus argv[%d] \"%s\"\n", argi, argv[argi]);
exit(1); break; \
case 0: break; \
-case 1: argi++; (*(value)) = strdup(*(value)); continue; \
-default: fprintf(stderr, "ICE %d\n", __LINE__); exit(1); return 1;}
+case 1: argi++; (*(value)) = strdup(__cb_str_value); continue; \
+default: fprintf(stderr, "ICE %d\n", __LINE__); exit(1); return 1;} \
+}

// Calls: callback(context, string value);
#define StringArgWithCallback(optname, callback, context) {const char*
__cb_str_value = NULL; switch(_StringArg(argc, argv, &argi, (optname),
&__cb_str_value)) { \
=======================================
--- /drendmain.cpp Wed Feb 23 02:54:10 2011 UTC
+++ /drendmain.cpp Sun May 12 03:07:44 2013 UTC
@@ -17,21 +17,16 @@

#include <ctype.h>

+#include "arghandler.h"
#include "Solver.h"
#include "tiger/mmaped.h"
#include "MapDrawer.h"
#include "renderDistricts.h"

-char* commandFileName = NULL;

-char* colorFileIn = NULL;
-char* colorFileOut = NULL;
-
-void runBasic( Solver& sov );
+void runBasic( Solver& sov, MapDrawer& mr, const char* colorFileIn, const
char* colorFileOut );
void runDrendCommandFile( Solver& sov );

-MapDrawer mr;
-
const char usage[] =
"usage: drend [--minlat 000.000000 | --minlatd delta from maxlat]\n"
" [--minlon 000.000000 | --minlond delta from maxlon]\n"
@@ -44,17 +39,51 @@
" [--pngW pixels wide][--pngH pixels high][--pngout out.png]\n"
;

-int main( int argc, char** argv ) {
+int main( int argc, const char** argv ) {
Solver sov;
- int i, nargc;
- char* upxfname = NULL;
- char* mppbfname = NULL;
- char* popdensityname = NULL;
+ int nargc;
+ const char* upxfname = NULL;
+ const char* mppbfname = NULL;
+ const char* popdensityname = NULL;
+
+ const char* commandFileName = NULL;
+
+ const char* colorFileIn = NULL;
+ const char* colorFileOut = NULL;
+
+ MapDrawer mr;

nargc=1;
sov.districtSetFactory = District2SetFactory;

- for ( i = 1; i < argc; i++ ) {
+ double minlatd = NAN;
+ double minlond = NAN;
+ double maxlatd = NAN;
+ double maxlond = NAN;
+
+ int argi = 1;
+ while (argi < argc) {
+#if 1
+ DoubleArg("minlat", &mr.minlat);
+ DoubleArg("minlatd", &minlatd);
+ DoubleArg("minlon", &mr.minlon);
+ DoubleArg("minlond", &minlond);
+ DoubleArg("maxlat", &mr.maxlat);
+ DoubleArg("maxlatd", &maxlatd);
+ DoubleArg("maxlon", &mr.maxlon);
+ DoubleArg("maxlond", &maxlond);
+ StringArg("f", &commandFileName);
+ StringArg("px", &upxfname);
+ StringArg("mppb", &mppbfname);
+ StringArg("colorsIn", &colorFileIn);
+ StringArg("colorsOut", &colorFileOut);
+ StringArg("density", &popdensityname);
+
+ // default:
+ argv[nargc] = argv[argi];
+ nargc++;
+ argi++;
+#else
if ( ! strcmp( argv[i], "--minlat" ) ) {
i++;
mr.minlat = strtod( argv[i], NULL );
@@ -101,7 +130,23 @@
argv[nargc] = argv[i];
nargc++;
}
+#endif
+ }
+
+ if (!isnan(minlatd)) {
+ mr.minlat = mr.maxlat + minlatd;
+ }
+ if (!isnan(maxlatd)) {
+ mr.maxlat = mr.minlat + maxlatd;
+ }
+ if (!isnan(minlond)) {
+ mr.minlon = mr.maxlon + minlond;
+ }
+ if (!isnan(maxlond)) {
+ mr.maxlon = mr.minlon + maxlond;
}
+
+
argv[nargc]=NULL;
int argcout = sov.handleArgs( nargc, argv );
if (argcout != 1) {
@@ -154,7 +199,7 @@
if ( commandFileName != NULL ) {
mr.runDrendCommandFile( sov, commandFileName );
} else {
- runBasic( sov );
+ runBasic( sov, mr, colorFileIn, colorFileOut );
}
if (popdensityname != NULL) {
mr.clearToBackgroundColor();
@@ -165,7 +210,7 @@
return 0;
}

-void runBasic( Solver& sov ) {
+void runBasic( Solver& sov, MapDrawer& mr, const char* colorFileIn, const
char* colorFileOut ) {
if ( colorFileIn != NULL ) {
FILE* cfi = fopen( colorFileIn, "r" );
if ( cfi == NULL ) {
=======================================
--- /fileio.cpp Sun Apr 3 18:18:14 2011 UTC
+++ /fileio.cpp Sun May 12 03:07:44 2013 UTC
@@ -27,7 +27,7 @@
extern FILE* blaf;
#endif

-int GeoData::open( char* inputname ) {
+int GeoData::open( const char* inputname ) {
int err;

fd = ::open( inputname, O_RDONLY );
@@ -684,12 +684,12 @@
return toret;
}
#endif
-GeoData* openUf1( char* inputname ) {
+GeoData* openUf1( const char* inputname ) {
Uf1* toret = new Uf1();
toret->open( inputname );
return toret;
}
-GeoData* openPlGeo( char* inputname ) {
+GeoData* openPlGeo( const char* inputname ) {
PlGeo* toret = new PlGeo();
toret->open( inputname );
return toret;
=======================================
--- /linkfixup.cpp Thu Feb 10 16:40:52 2011 UTC
+++ /linkfixup.cpp Sun May 12 03:07:44 2013 UTC
@@ -44,7 +44,7 @@

Node* initNodesFromLinksFile( GeoData* gd, const char* inputname );

-int main( int argc, char** argv ) {
+int main( int argc, const char** argv ) {
Solver sov;
int i, nargc;
const char* foname = NULL;
=======================================
--- /makeopts/Darwin.pre Tue Jul 15 15:24:17 2008 UTC
+++ /makeopts/Darwin.pre Sun May 12 03:07:44 2013 UTC
@@ -1,6 +1,6 @@
# Compile for the old standby ppc and for the latest hotness x86_64
# Need /usr/X11 in path for libpng
-CCOMMONFLAGS:=-arch ppc -arch x86_64 -I/usr/X11/include -L/usr/X11/lib
+#CCOMMONFLAGS:=-arch ppc -arch x86_64 -I/usr/X11/include -L/usr/X11/lib
# -MMD is incompatible with multiple -arch flags.
# Use an alternate option like this if just using one architecture
# for better development compilation.
=======================================
--- /nonguimain.cpp Wed Mar 5 02:35:49 2008 UTC
+++ /nonguimain.cpp Sun May 12 03:07:44 2013 UTC
@@ -73,7 +73,7 @@
#endif


-int main( int argc, char** argv ) {
+int main( int argc, const char** argv ) {
Solver sov;
return sov.main( argc, argv );
}
=======================================
--- /notes.txt Mon May 28 19:10:39 2012 UTC
+++ /notes.txt Sun May 12 03:07:44 2013 UTC
@@ -192,3 +192,9 @@

TODO: set G+ on the website
https://plusone.google.com/_/+1/confirm?hl=en&url=${url}
+
+2013-05-04 16:11:54 EDT (Saturday, May 04 04:11:54 PM)
+
+analyze and render 2013 actual districts
+
+./analyze -P ../../CT/ct.pb -d 5 --csv-solution --loadSolution
09_CT_CD113.txt
=======================================
--- /rtaToDsz.cpp Thu Jun 11 04:36:19 2009 UTC
+++ /rtaToDsz.cpp Sun May 12 03:07:44 2013 UTC
@@ -62,10 +62,10 @@
return 0;
}

-int main( int argc, char** argv ) {
+int main( int argc, const char** argv ) {
Solver sov;
int i, nargc;
- vector<char*> filenames;
+ vector<const char*> filenames;

nargc=1;

@@ -97,7 +97,7 @@
for ( i = 0; i < sov.gd->numPoints; i++ ) {
sov.winner[i] = NODISTRICT;
}
- for (vector<char*>::iterator fni = filenames.begin();
+ for (vector<const char*>::iterator fni = filenames.begin();
fni != filenames.end(); ++fni) {
if (processRTA(&sov, *fni) < 0) {
return 1;

==============================================================================
Revision: 8f05667c8624
Branch: default
Author: Brian Olson <brian...@gmail.com>
Date: Sat May 18 14:31:54 2013 UTC
Log: cleanup
http://code.google.com/p/redistricter/source/detail?r=8f05667c8624

Modified:
/Makefile
/Solver.h
/makeopts/Darwin.pre

=======================================
--- /Makefile Sun Jun 5 15:32:18 2011 UTC
+++ /Makefile Sat May 18 14:31:54 2013 UTC
@@ -132,10 +132,10 @@
./districter2 -U build/input.uf1 -g 100 --pngout fl_test.png --pngW 400
--pngH 400 --oldCDs -d -10 -o fl_test_oz

pw: pw.cpp
- g++ -Wall ${LDPNG} pw.cpp -lz -o pw -g
+ $(CXX) ${CXXFLAGS} -Wall ${LDPNG} pw.cpp -lz -o pw -g

dumpBinLog: dumpBinLog.cpp redata.pb.cc redata.pb.h
- g++ -lz -lprotobuf -lpthread dumpBinLog.cpp redata.pb.cc -o dumpBinLog
+ $(CXX) ${CXXFLAGS} -lz -lprotobuf -lpthread dumpBinLog.cpp redata.pb.cc
-o dumpBinLog

xcode:
xcodebuild -alltargets -project guidistricter.xcodeproj
=======================================
--- /Solver.h Sun May 12 03:07:44 2013 UTC
+++ /Solver.h Sat May 18 14:31:54 2013 UTC
@@ -109,8 +109,6 @@
int saveZSolution( const char* filename );
int loadZSolution( const char* filename );
int loadCsvSolution( const char* filename );
- /* from loadname */
- int loadSolution( const char* loadname );
void initSolution();
void initSolutionFromOldCDs();
void init();
@@ -122,7 +120,8 @@
void doPNG();
void doPNG(POPTYPE* soln, const char* outname);
//void doPNG_r( unsigned char* data, unsigned char** rows, int pngWidth,
int pngHeight, const char* pngname );
-#endif
+#endif /* WITH_PNG */
+
void printDistricts(const char* filename);
void printDistricts() {
printDistricts(distfname);
=======================================
--- /makeopts/Darwin.pre Sun May 12 03:07:44 2013 UTC
+++ /makeopts/Darwin.pre Sat May 18 14:31:54 2013 UTC
@@ -5,3 +5,4 @@
# Use an alternate option like this if just using one architecture
# for better development compilation.
#CCOMMONFLAGS:=-m64 -I/usr/X11/include -L/usr/X11/lib -MMD
+CCOMMONFLAGS:=-MMD

==============================================================================
Revision: cf03356a5e47
Branch: default
Author: Brian Olson <brian...@gmail.com>
Date: Sat May 25 18:19:46 2013 UTC
Log: Make drend easier to use, detecting number of districts from
loaded solution. Make district allocation lazy to accommodate this.
http://code.google.com/p/redistricter/source/detail?r=cf03356a5e47

Modified:
/District2.cpp
/Solver.cpp
/Solver.h
/analyze.cpp
/drendmain.cpp
/newerthan.py
/notes.txt

=======================================
--- /District2.cpp Thu Feb 10 04:10:08 2011 UTC
+++ /District2.cpp Sat May 25 18:19:46 2013 UTC
@@ -671,7 +671,7 @@
Solver* sov = d2set->sov;
Node* nodes = sov->nodes;
POPTYPE* winner = sov->winner;
- District2* dists = ((District2Set*)(sov->dists))->dists;
+ District2* dists = ((District2Set*)(sov->getDistricts()))->dists;
const GeoData* gd = sov->gd;

POPTYPE odi;
@@ -926,7 +926,7 @@
Solver* sov = d2set->sov;
Node* nodes = sov->nodes;
POPTYPE* winner = sov->winner;
- District2* dists = ((District2Set*)(sov->dists))->dists;
+ District2* dists = ((District2Set*)(sov->getDistricts()))->dists;
const GeoData* gd = sov->gd;
//double districtPopTarget = sov->districtPopTarget;
// best neighbor to claim
@@ -1044,7 +1044,7 @@
const GeoData* gd = sov->gd;
if ( mi != -1 ) {
POPTYPE* winner = sov->winner;
- District2* dists = ((District2Set*)(sov->dists))->dists;
+ District2* dists = ((District2Set*)(sov->getDistricts()))->dists;
int err = unsetDist( d, mi );
if ( err < 0 ) {
sov->centerOnPoint( mi );
=======================================
--- /Solver.cpp Sun May 12 03:07:44 2013 UTC
+++ /Solver.cpp Sat May 25 18:19:46 2013 UTC
@@ -82,10 +82,9 @@
Solver::Solver() :
districts( 5 ), totalpop( 0.0 ), districtPopTarget( 0.0 ),
nodes( NULL ), allneigh( NULL ), winner( NULL ),
- districtSetFactory( NULL ), dists( NULL ),
+ districtSetFactory( NULL ), _dists( NULL ),
inputname( oldDefaultInputName ), generations( -1 ),
dumpname( NULL ),
- loadname( NULL ),
initMode( initWithNewDistricts ),
solutionLogPrefix( NULL ), solutionLogInterval( 100 ),
solutionLogCountdown( 0 ),
#if WITH_PNG
@@ -111,7 +110,9 @@
_point_draw_array( NULL ),
lastGenDrawn( -1 ), vertexBufferObject(0), colorBufferObject(0),
linesBufferObject(0),
drawHistoryPos( 0 ),
- maxSpreadFraction( 1000.0 ), maxSpreadAbsolute( 9.0e9 )
+ maxSpreadFraction( 1000.0 ), maxSpreadAbsolute( 9.0e9 ),
+ loadFormat( DetectFormat ),
+ loadname( NULL )
{
//_link_draw_array( NULL ),
}
@@ -125,8 +126,8 @@
if ( winner != NULL ) {
delete [] winner;
}
- if ( dists != NULL ) {
- delete dists;
+ if ( _dists != NULL ) {
+ delete _dists;
}
if ( gd != NULL ) {
delete gd;
@@ -192,6 +193,7 @@
readLinksFile(NULL);
}

+#if 0
if ( districts <= 0 ) {
int tdistricts = gd->numDistricts();
if ( tdistricts > 1 ) {
@@ -200,6 +202,7 @@
districts = districts * -1;
}
}
+#endif

minx = gd->minx;
maxx = gd->maxx;
@@ -453,23 +456,27 @@
#endif
}

-void Solver::allocSolution() {
- winner = new POPTYPE[gd->numPoints];
- assert(winner != NULL);
- for ( int i = 0; i < gd->numPoints; i++ ) {
- winner[i] = NODISTRICT;
- }
+DistrictSet* Solver::getDistricts() { // lazy allocating caching accessor
if ( districtSetFactory != NULL ) {
- dists = districtSetFactory(this);
+ _dists = districtSetFactory(this);
} else {
#if 1
- dists = new NearestNeighborDistrictSet(this);
+ _dists = new NearestNeighborDistrictSet(this);
#else
- dists = new District2Set(this);
+ _dists = new District2Set(this);
#endif
}
- assert(dists != NULL);
- dists->alloc(districts);
+ assert(_dists != NULL);
+ _dists->alloc(districts); // TODO: mave this into lazy allocating within
a DistrictSet
+ return _dists;
+}
+
+void Solver::allocSolution() {
+ winner = new POPTYPE[gd->numPoints];
+ assert(winner != NULL);
+ for ( int i = 0; i < gd->numPoints; i++ ) {
+ winner[i] = NODISTRICT;
+ }
}

#define ZFILE_VERSION 4
@@ -523,6 +530,7 @@
#define compressBound( n ) ( (n) + ((n) / 500) + 12 )
#endif

+// TODO: Write magic number prefix bytes? "BDSZ" maybe? (Brian's District
Solution (Zlib compressed))
// Format (variable endianness, use fileversion to detect):
// uint32 fileversion
// uint32 numPoints
@@ -553,11 +561,17 @@
close( dumpfd );
return -1;
}
-

int Solver::saveZSolution( const char* filename ) {
return ::saveZSolution( filename, winner, gd->numPoints );
}
+
+// todo: template?
+int max(int a, int b) {
+ if (a > b) return a;
+ return b;
+}
+
int Solver::loadZSolution( const char* filename ) {
ZFILE_INT ti;
uLongf unzlen;
@@ -608,13 +622,31 @@
if ( endianness ) {
assert( sizeof(POPTYPE) == 1 );
}
- dists->initFromLoadedSolution();
+ if (districts == -1) {
+ int maxd = -1;
+ for (int i = 0; i < gd->numPoints; ++i) {
+ maxd = max(winner[i], maxd);
+ }
+ districts = maxd + 1;
+ }
+ getDistricts()->initFromLoadedSolution();
return close( readfd );
loadZFail:
free( zb );
close( readfd );
return -1;
}
+
+static bool districtNumberIsValid(int d, int districts) {
+ if (d < 1) return false;
+ if (districts == -1) {
+ if (d > POPTYPE_MAX) return false;
+ } else {
+ if (d > districts) return false;
+ }
+ return true;
+}
+
int Solver::loadCsvSolution( const char* filename ) {
FILE* fin;
if (0 == strcmp(filename, "-")) {
@@ -634,6 +666,9 @@
int errcount = 0;
memset(winner, NODISTRICT, gd->numPoints);
int setcount = 0;
+ int maxd = -1;
+
+
while (line != NULL) {
char* c = line;
while ((c != '\0') && (!isdigit(*c))) {
@@ -665,7 +700,7 @@
err = -1;
break;
}
- } else if ((district < 1) || (district > districts)) {
+ } else if (!districtNumberIsValid(district, districts)) {
fprintf(stderr, "winner[%d]=%lu would be out of range (1..%d)\n",
index, district, districts);
errcount++;
if (errcount > 20) {
@@ -674,6 +709,7 @@
}
} else {
winner[index] = district - 1;
+ maxd = max(maxd, winner[index]);
setcount++;
}
line = fgets(lineBuf, MAX_LINE_LENGTH, fin);
@@ -692,13 +728,44 @@
}
}
fprintf(stderr, "set %d points of %d, %d not set\n", setcount,
gd->numPoints, notset);
- dists->initFromLoadedSolution();
+ if (districts == -1) {
+ districts = maxd + 1;
+ } else {
+ if (maxd + 1 != districts) {
+ fprintf(stderr, "expected %d districts but got %d\n", districts, maxd +
1);
+ }
+ }
+ getDistricts()->initFromLoadedSolution();
return err;
}


+int Solver::loadSolution() {
+ switch (loadFormat) {
+ case DszFormat:
+ return loadZSolution(loadname);
+ break;
+ case CsvFormat:
+ return loadCsvSolution(loadname);
+ break;
+ default:
+ fprintf(stderr, "loadSolution file type detection not implemented\n");
+ assert(false);
+ }
+ return -1;
+}
+
+
+bool Solver::hasSolutionToLoad() {
+ return (loadname != NULL) && (loadname[0] != '\0');
+}
+
+const char* Solver::getSolutionFilename() const {
+ return loadname;
+}
+
void Solver::initSolution() {
- dists->initNewRandomStart();
+ getDistricts()->initNewRandomStart();
}

void Solver::initSolutionFromOldCDs() {
@@ -717,7 +784,7 @@
assert( d < districts );
winner[i] = d;
}
- dists->initFromLoadedSolution();
+ getDistricts()->initFromLoadedSolution();
}

void Solver::init() {
@@ -728,14 +795,14 @@
#endif

int Solver::step() {
- int err = dists->step();
+ int err = getDistricts()->step();
gencount++;
return err;
}

#if 1
void Solver::printDistricts(const char* filename) {
- dists->print(filename);
+ getDistricts()->print(filename);
}
#else
void Solver::printDistrcts() {
@@ -754,7 +821,7 @@

SolverStats* Solver::getDistrictStats() {
SolverStats* stats = new SolverStats();
- dists->getStats(stats);
+ getDistricts()->getStats(stats);
stats->generation = gencount;
return stats;
}
@@ -919,7 +986,8 @@
"-g n generations (steps) to run\n"
"-d n number of districts to create\n"
"-o file dump solution here\n"
-"-loadSolution file load previously generated solution\n"
+"-loadSolution file load previously generated solution (dsz format)\n"
+"-csv-solution file load census/portable csv block association file\n"
"-pngout file where to write png of final solution\n"
"-pngW n width of image to make\n"
"-pngH n height of image to make\n"
@@ -964,8 +1032,9 @@
IntArg("g", &generations);
IntArg("d", &districts);
StringArgWithCopy("o", &dumpname);
- StringArgWithCopy("r", &loadname);
- StringArgWithCopy("loadSolution", &loadname);
+ StringArgWithCallback("r", setDszLoadname, NULL);
+ StringArgWithCallback("loadSolution", setDszLoadname, NULL);
+ StringArgWithCallback("csv-solution", setCsvLoadname, NULL);
StringArgWithCopy("distout", &distfname); // deprecated?
StringArgWithCopy("coordout", &coordfname); // deprecated?
#if WITH_PNG
@@ -1055,6 +1124,18 @@
}
return argcout;
}
+
+
+void Solver::setCsvLoadname(void* context, const char* filename) {
+ loadname = strdup(filename);
+ loadFormat = CsvFormat;
+}
+void Solver::setDszLoadname(void* context, const char* filename) {
+ loadname = strdup(filename);
+ loadFormat = DszFormat;
+}
+
+

#if WITH_PNG
static char bestStdPng[] = "bestStd.png";
@@ -1128,7 +1209,7 @@
gd->close();

if ( generations == -1 ) {
- generations = dists->defaultGenerations();
+ generations = getDistricts()->defaultGenerations();
}
SolverStats* bestStd = NULL;
SolverStats* bestSpread = NULL;
=======================================
--- /Solver.h Sat May 18 14:31:54 2013 UTC
+++ /Solver.h Sat May 25 18:19:46 2013 UTC
@@ -26,12 +26,12 @@
int* allneigh;
POPTYPE* winner;
DistrictSet* (*districtSetFactory)(Solver*);
- DistrictSet* dists;
+ DistrictSet* _dists;
+ DistrictSet* getDistricts(); // lazy allocating caching accessor

const char* inputname;
int generations;
char* dumpname;
- char* loadname;
enum initModeEnum {
initWithNewDistricts = 1,
initWithOldDistricts
@@ -107,6 +107,10 @@
void initNodes();
void allocSolution();
int saveZSolution( const char* filename );
+ int loadSolution();
+ bool hasSolutionToLoad(); // did handleArgs get something?
+ const char* getSolutionFilename() const;
+ // immediate solution load .. probably for drend in animation mode
int loadZSolution( const char* filename );
int loadCsvSolution( const char* filename );
void initSolution();
@@ -169,7 +173,7 @@
int main( int argc, const char** argv );

inline int setDist( POPTYPE d, int i ) {
- return (*dists)[(d)].add( this, (i), (d) );
+ return (*getDistricts())[(d)].add( this, (i), (d) );
}

int debugDistrictNumber;
@@ -181,6 +185,18 @@
int getDistrictStats( char* str, int len );

static const char* argHelp;
+
+ private:
+ enum {
+ DszFormat = 1,
+ CsvFormat = 2,
+ DetectFormat = 3,
+ } loadFormat;
+ char* loadname;
+
+ // callbacks for arghanlding.h StringArgWithCallback
+ void setCsvLoadname(void* context, const char* filename);
+ void setDszLoadname(void* context, const char* filename);
};

class SolverStats {
=======================================
--- /analyze.cpp Sun May 12 03:07:44 2013 UTC
+++ /analyze.cpp Sat May 25 18:19:46 2013 UTC
@@ -89,8 +89,8 @@
bool distrow = true;
bool distcol = false;
bool quiet = false;
- bool loadSolutionCsvMode = false;
- const char* csvInName = NULL;
+ //bool loadSolutionCsvMode = false;
+ //const char* csvInName = NULL;
const char* exportPath = NULL;

vector<const char*> compareArgs;
@@ -113,7 +113,7 @@
BoolArg("distrow", &distrow);
BoolArg("distcol", &distcol);
StringArg("export", &exportPath);
- StringArg("csv-solution", &csvInName);
+ //StringArg("csv-solution", &csvInName);

// default:
argv[nargc] = argv[argi];
@@ -122,10 +122,12 @@
}
argv[nargc]=NULL;

+#if 0
if (csvInName != NULL) {
sov.loadname = strdup(csvInName);
loadSolutionCsvMode = true;
}
+#endif

int argcout = sov.handleArgs(nargc, argv);
if (argcout != 1) {
@@ -184,11 +186,14 @@
sov.load();
sov.initNodes();
sov.allocSolution();
- if (sov.loadname != NULL) {
+ if (sov.hasSolutionToLoad()) {
if (!quiet) {
- fprintf(stdout, "loading \"%s\"\n", sov.loadname);
+ fprintf(stdout, "loading \"%s\"\n", sov.getSolutionFilename());
}
- if (loadSolutionCsvMode) {
+ if (sov.hasSolutionToLoad()) {
+ sov.loadSolution();
+#if 0
+ } else if (loadSolutionCsvMode) {
if (sov.loadCsvSolution(sov.loadname) < 0) {
return 1;
}
@@ -196,6 +201,7 @@
if (sov.loadZSolution(sov.loadname) < 0) {
return 1;
}
+#endif
}
if (!quiet) {
char* statstr = new char[10000];
=======================================
--- /drendmain.cpp Sun May 12 03:07:44 2013 UTC
+++ /drendmain.cpp Sat May 25 18:19:46 2013 UTC
@@ -157,7 +157,7 @@
return 1;
}

- if ( sov.loadname == NULL && commandFileName == NULL ) {
+ if ( (!sov.hasSolutionToLoad()) && commandFileName == NULL ) {
fprintf(stderr,"useless drend, null loadname and null command file
name\n");
exit(1);
}
@@ -169,9 +169,9 @@

sov.initNodes();
sov.allocSolution();
- if ( sov.loadname != NULL ) {
- fprintf( stdout, "loading \"%s\"\n", sov.loadname );
- if ( sov.loadZSolution( sov.loadname ) < 0 ) {
+ if ( sov.hasSolutionToLoad() ) {
+ fprintf( stdout, "loading \"%s\"\n", sov.getSolutionFilename() );
+ if ( sov.loadSolution() < 0 ) {
return 1;
}
char* statstr = new char[10000];
=======================================
--- /newerthan.py Thu Jan 27 13:04:44 2011 UTC
+++ /newerthan.py Sat May 25 18:19:46 2013 UTC
@@ -16,7 +16,7 @@
return True
return sa.st_mtime > sb.st_mtime

-def any_newerthan(alist, b):
+def any_newerthan(alist, b, noSourceCallback=None):
"""Return true if b doesn't exist or anything in a is newerthan b."""
try:
sb = os.stat(b)
@@ -26,7 +26,8 @@
try:
sa = os.stat(a)
except:
- # item in alist doesn't exist, maybe raise an Exception?
+ if noSourceCallback is not None:
+ noSourceCallback(a)
return False
if sa.st_mtime > sb.st_mtime:
return True
=======================================
--- /notes.txt Sun May 12 03:07:44 2013 UTC
+++ /notes.txt Sat May 25 18:19:46 2013 UTC
@@ -198,3 +198,10 @@
analyze and render 2013 actual districts

./analyze -P ../../CT/ct.pb -d 5 --csv-solution --loadSolution
09_CT_CD113.txt
+
+drend --csv-solution 09_CT_CD113.txt -P ct.pb --mppb=CT.mppb
--pngout=ct113.png
+
+drend --csv-solution=25_MA_CD113.txt -P=ma.pb --mppb=MA.mppb
--pngout=/tmp/MA_us2013.png -d=-1
+
+Make drend easier to use, detecting number of districts from loaded
solution. Make district allocation lazy to accommodate this.
+

==============================================================================
Revision: 0d6164e1f1a9
Branch: default
Author: Brian Olson <brian...@gmail.com>
Date: Sat May 25 21:24:58 2013 UTC
Log: a bunch of work on rendering 2013 actual districts for comparison
http://code.google.com/p/redistricter/source/detail?r=0d6164e1f1a9

Added:
/countFieldFreq.py
/render_2013_actual.py
Modified:
/Solver.cpp
/Solver.h
/analyze_submissions.py
/newerthan.py
/notes.txt

=======================================
--- /dev/null
+++ /countFieldFreq.py Sat May 25 21:24:58 2013 UTC
@@ -0,0 +1,72 @@
+#!/usr/bin/python
+
+import csv
+
+
+class FFCounter(object):
+ def __init__(self):
+ self._counters = None
+ self.reccount = 0
+
+ def _genCounters(self, cols):
+ self._counters = []
+ for i in xrange(0, cols):
+ self._counters.append(dict())
+
+ def countFeildFreq(self, fin, fields=None):
+ if (self._counters is None) and fields:
+ self._counters = [None] * (max(fields) + 1)
+ #print 'counters = %r, fields=%r' % (self._counters, fields)
+ for i in fields:
+ self._counters[i] = dict()
+ reader = csv.reader(fin)
+ for row in reader:
+ self.reccount += 1
+ if self._counters is None:
+ self._genCounters(len(row))
+ for i, d in enumerate(self._counters):
+ if d is not None:
+ if i < len(row):
+ v = row[i]
+ else:
+ v = 'None'
+ d[v] = d.get(v, 0) + 1
+
+ def __str__(self):
+ outl = []
+ for i, d in enumerate(self._counters):
+ if not d:
+ continue
+ outl.append('%s:' % (i,))
+ dk = d.keys()
+ dk.sort()
+ for k in dk:
+ dv = d[k]
+ outl.append('\t%s: %s' % (k, dv))
+ return '\n'.join(outl)
+
+
+
+if __name__ == '__main__':
+ import optparse
+ import sys
+ import time
+
+ start = time.time()
+ op = optparse.OptionParser()
+ op.add_option('-f', '--field', dest='fields', action='append',
type='int', default=[])
+ options, args = op.parse_args()
+ c = FFCounter()
+ if args:
+ for arg in args:
+ fin = open(arg, 'rb')
+ c.countFeildFreq(fin, options.fields)
+ else:
+ c.countFeildFreq(sys.stdin, options.fields)
+
+ end = time.time()
+ sys.stderr.write('%s records in %s seconds\n' % (c.reccount, end -
start))
+
+ print c
+
+
=======================================
--- /dev/null
+++ /render_2013_actual.py Sat May 25 21:24:58 2013 UTC
@@ -0,0 +1,125 @@
+#!/usr/bin/python
+
+"""Writes out per-state map images to current directory.
+Usage:
+render_2013_actual.py --datadir=/Volumes/bulktogo/redata/2010
--districtdir=/Volumes/bulktogo/redata/2010/2013_actual/cd113
+"""
+
+# drend --csv-solution=09_CT_CD113.txt -P=ct.pb --mppb=CT.mppb
--pngout=ct113.png
+
+import csv
+import logging
+import optparse
+import os
+import re
+import subprocess
+import sys
+
+
+from analyze_submissions import measure_race
+from newerthan import newerthan, any_newerthan
+import states
+
+
+def csvToSimpleCsv(csvpath, outpath):
+ """Convert CSV with district 'number' that could be '00A' '01A' 'MISC'
to simple numeric district numbers."""
+ fin = open(csvpath, 'rb')
+ reader = csv.reader(fin)
+ row = reader.next()
+ # expect header row either:
+ # BLOCKID,CD113
+ # BLOCKID,DISTRICT,NAME
+ assert row[0] == 'BLOCKID'
+ assert ((row[1] == 'CD113') or (row[1] == 'DISTRICT'))
+ unmapped = []
+ districts = set()
+ for row in reader:
+ unmapped.append( (row[0], row[1]) )
+ districts.add(row[1])
+ fin.close()
+ dl = list(districts)
+ dl.sort()
+ dmap = {}
+ for i, dname in enumerate(dl):
+ dmap[dname] = i + 1 # 1 based csv file district numbering
+ fout = open(outpath, 'wb')
+ writer = csv.writer(fout)
+ for blockid, dname in unmapped:
+ writer.writerow( (blockid, dmap[dname]) )
+ fout.close()
+
+
+def main():
+ srcdir_ = os.path.dirname(os.path.abspath(__file__))
+
+ op = optparse.OptionParser()
+ op.add_option('--datadir', dest='datadir')
+ op.add_option('--districtdir', dest='distdir', help='where the district
CSV files live')
+
+ options, args = op.parse_args()
+
+ stDistFiles = {}
+ anyError = False
+
+ distdirall = os.listdir(options.distdir)
+
+ statefileRawRe = re.compile('.._(..)_.*\.txt', re.IGNORECASE)
+
+ for fname in distdirall:
+ m = statefileRawRe.match(fname)
+ if m:
+ stu = m.group(1).upper()
+ if states.nameForPostalCode(stu) is not None:
+ # winner
+ old = stDistFiles.get(stu)
+ if old is None:
+ stDistFiles[stu] = fname
+ else:
+ logging.error('collision %s -> %s AND %s', stu, old, fname)
+ anyError = True
+
+ #for k,v in stDistFiles.iteritems():
+ # print '%s\t%s' % (k, v)
+
+ if anyError:
+ sys.exit(1)
+
+ drendpath = os.path.join(srcdir_, 'drend')
+ if not os.path.exists(drendpath):
+ logging.error('no drend binary at %r', drendpath)
+ sys.exit(1)
+
+ def noSource(sourceName):
+ logging.error('missing source %s', sourceName)
+
+ for k,v in stDistFiles.iteritems():
+ print k
+ stl = k.lower()
+ stu = k.upper()
+ csvpath = os.path.join(options.distdir, v)
+ simplecsvpath = os.path.join(options.distdir, stu + '.csv')
+ stdir = os.path.join(options.datadir, stu)
+ pb = os.path.join(stdir, stl + '.pb')
+ mppb = os.path.join(stdir, stu + '.mppb')
+ zipname = os.path.join(stdir, 'zips', stl + '2010.pl.zip')
+ htmlout = os.path.join(stu + '.html')
+ pngout = stu + '.png'
+ if any_newerthan( (pb, mppb, csvpath, zipname), (pngout, htmlout),
noSourceCallback=noSource):
+ if newerthan(csvpath, simplecsvpath):
+ csvToSimpleCsv(csvpath, simplecsvpath)
+ if any_newerthan( (pb, mppb, simplecsvpath), pngout):
+ cmd = [drendpath, '-d=-1', '-P', pb, '--mppb',
mppb, '--csv-solution', simplecsvpath, '--pngout', pngout]
+ print ' '.join(cmd)
+ p = subprocess.Popen(cmd, stdin=None, stdout=subprocess.PIPE,
shell=False)
+ retcode = p.wait()
+ if retcode != 0:
+ logging.error('cmd `%s` retcode %s log %s', cmd, retcode,
p.stdout.read())
+ sys.exit(1)
+ if any_newerthan( (pb, mppb, simplecsvpath, zipname), htmlout):
+ measure_race(stl, '-1', pb, simplecsvpath, htmlout, zipname,
printcmd=lambda x: sys.stderr.write(' '.join(x) + '\n'))
+
+
+
+if __name__ == '__main__':
+ main()
+
=======================================
--- /Solver.cpp Sat May 25 18:19:46 2013 UTC
+++ /Solver.cpp Sat May 25 21:24:58 2013 UTC
@@ -701,12 +701,17 @@
break;
}
} else if (!districtNumberIsValid(district, districts)) {
- fprintf(stderr, "winner[%d]=%lu would be out of range (1..%d)\n",
index, district, districts);
errcount++;
+ if (errcount < 20) {
+ fprintf(stderr, "winner[%d]=%lu would be out of range (1..%d)\n",
index, district, districts);
+ }
+#if false
if (errcount > 20) {
err = -1;
break;
}
+#endif
+ winner[index] = NODISTRICT;
} else {
winner[index] = district - 1;
maxd = max(maxd, winner[index]);
@@ -749,7 +754,16 @@
return loadCsvSolution(loadname);
break;
default:
- fprintf(stderr, "loadSolution file type detection not implemented\n");
+ if (strstr(loadname, ".dsz") != NULL) {
+ return loadZSolution(loadname);
+ }
+ if (strstr(loadname, ".csv") != NULL) {
+ return loadCsvSolution(loadname);
+ }
+ if (strstr(loadname, ".text") != NULL) {
+ return loadCsvSolution(loadname);
+ }
+ fprintf(stderr, "loadSolution could not guess type for '%s'\n", loadname);
assert(false);
}
return -1;
@@ -1033,7 +1047,7 @@
IntArg("d", &districts);
StringArgWithCopy("o", &dumpname);
StringArgWithCallback("r", setDszLoadname, NULL);
- StringArgWithCallback("loadSolution", setDszLoadname, NULL);
+ StringArgWithCallback("loadSolution", setLoadname, NULL);
StringArgWithCallback("csv-solution", setCsvLoadname, NULL);
StringArgWithCopy("distout", &distfname); // deprecated?
StringArgWithCopy("coordout", &coordfname); // deprecated?
@@ -1134,6 +1148,10 @@
loadname = strdup(filename);
loadFormat = DszFormat;
}
+void Solver::setLoadname(void* context, const char* filename) {
+ loadname = strdup(filename);
+ loadFormat = DetectFormat;
+}



=======================================
--- /Solver.h Sat May 25 18:19:46 2013 UTC
+++ /Solver.h Sat May 25 21:24:58 2013 UTC
@@ -197,6 +197,7 @@
// callbacks for arghanlding.h StringArgWithCallback
void setCsvLoadname(void* context, const char* filename);
void setDszLoadname(void* context, const char* filename);
+ void setLoadname(void* context, const char* filename);
};

class SolverStats {
=======================================
--- /analyze_submissions.py Sun Jun 3 16:41:01 2012 UTC
+++ /analyze_submissions.py Sat May 25 21:24:58 2013 UTC
@@ -145,6 +145,32 @@
maxMinRe = re.compile(r'max=([0-9]+).*min=([0-9]+)')


+def measure_race(stl, numd, pbfile, solution, htmlout, zipname,
exportpath=None, bindir=None, printcmd=None):
+ if not os.path.exists(zipname):
+ logging.error('could not measure race without %s', zipname)
+ return
+ zf = zipfile.ZipFile(zipname, 'r')
+ part1name = stl + '000012010.pl'
+ if bindir is None:
+ bindir = srcdir_
+
+ analyzebin = os.path.join(bindir, 'analyze')
+ cmd = [analyzebin, '--compare', ':5,7,8,9,10,11,12,13',
+ '--labels', 'total,white,black,native,asian,pacific,other,mixed',
+ '--dsort', '1', '--notext',
+ '--html', htmlout,
+ '-P', pbfile, '-d', numd, '--loadSolution', solution]
+ if exportpath:
+ cmd += ['--export', exportpath]
+
+ if printcmd:
+ printcmd(cmd)
+ p = subprocess.Popen(cmd, shell=False, stdin=subprocess.PIPE)
+ p.stdin.write(zf.read(part1name))
+ p.stdin.close()
+ p.wait()
+
+
def loadDatadirConfigurations(configs, datadir, statearglist=None,
configPathFilter=None):
"""Store to configs[config name]."""
for xx in os.listdir(datadir):
@@ -598,32 +624,15 @@

def measureRace(self, cname, solution, htmlout, exportpath):
config = self.config[cname]
- #zipname = 'VA/zips/va2010.pl.zip'
stl = cname[0:2].lower()
zipname = os.path.join(config.datadir, 'zips', stl + '2010.pl.zip')
if not os.path.exists(zipname):
logging.error('could not measure race without %s', zipname)
return
- zf = zipfile.ZipFile(zipname, 'r')
- part1name = stl + '000012010.pl'
- #part1f = zf.open(part1name, 'r')
- #p1csv = csv.reader(part1f)
numd = config.args['-d']
pbfile = config.args['-P']

- analyzebin = os.path.join(self.options.bindir, 'analyze')
- cmd = [analyzebin, '--compare', ':5,7,8,9,10,11,12,13',
- '--labels', 'total,white,black,native,asian,pacific,other,mixed',
- '--dsort', '1', '--notext',
- '--html', htmlout,
- '-P', pbfile, '-d', numd, '--loadSolution', solution]
- if exportpath:
- cmd += ['--export', exportpath]
-
- p = subprocess.Popen(cmd, shell=False, stdin=subprocess.PIPE)
- p.stdin.write(zf.read(part1name))
- p.stdin.close()
- p.wait()
+ measure_race(stl, numd, pbfile, solution, htmlout, zipname, exportpath,
self.options.bindir)

def processFailedSubmissions(self, configs, cname):
c = self.db.cursor()
=======================================
--- /newerthan.py Sat May 25 18:19:46 2013 UTC
+++ /newerthan.py Sat May 25 21:24:58 2013 UTC
@@ -16,12 +16,40 @@
return True
return sa.st_mtime > sb.st_mtime

-def any_newerthan(alist, b, noSourceCallback=None):
- """Return true if b doesn't exist or anything in a is newerthan b."""
+
+def _mystat_one(x):
+ """Return (is_missing, st_mtime)"""
try:
- sb = os.stat(b)
- except:
- return True
+ st = os.stat(x)
+ return False, st.st_mtime
+ except OSError, oe:
+ return True, None
+
+
+def get_oldest_mtime(b):
+ """Return (any_missing, oldest_mtime)"""
+ any_missing = False
+ oldest_mtime = None
+ if isinstance(b, basestring):
+ return _mystat_one(b)
+ try:
+ for x in b:
+ try:
+ st = os.stat(x)
+ if (oldest_mtime is None) or (st.st_mtime < oldest_mtime):
+ oldest_mtime = st.st_mtime
+ except OSError, oe:
+ any_missing = True
+ except TypeError, te:
+ # x is not iterable
+ return _mystat_one(b)
+ return any_missing, oldest_mtime
+
+
+def any_newerthan(alist, b, noSourceCallback=None):
+ """Return true if b doesn't exist or anything in a is newerthan b.
+ b may be a single path or iterable."""
+ out, out_mtime = get_oldest_mtime(b)
for a in alist:
try:
sa = os.stat(a)
@@ -29,6 +57,6 @@
if noSourceCallback is not None:
noSourceCallback(a)
return False
- if sa.st_mtime > sb.st_mtime:
- return True
- return False
+ if (out_mtime is not None) and (sa.st_mtime > out_mtime):
+ out = True
+ return out
=======================================
--- /notes.txt Sat May 25 18:19:46 2013 UTC
+++ /notes.txt Sat May 25 21:24:58 2013 UTC
@@ -205,3 +205,7 @@

Make drend easier to use, detecting number of districts from loaded
solution. Make district allocation lazy to accommodate this.

+~/src/redistricter/render_2013_actual.py
--datadir=/Volumes/bulktogo/redata/2010
--districtdir=/Volumes/bulktogo/redata/2010/2013_actual/cd
+~/src/redistricter/render_2013_actual.py
--datadir=/Volumes/bulktogo/redata/2010
--districtdir=/Volumes/bulktogo/redata/2010/2013_actual/sldu
+~/src/redistricter/render_2013_actual.py
--datadir=/Volumes/bulktogo/redata/2010
--districtdir=/Volumes/bulktogo/redata/2010/2013_actual/sldl
+

==============================================================================
Revision: 5cc57190fefc
Branch: default
Author: Brian Olson <brian...@gmail.com>
Date: Mon May 27 18:25:38 2013 UTC
Log: fix lazy allocator
http://code.google.com/p/redistricter/source/detail?r=5cc57190fefc

Modified:
/Solver.cpp

=======================================
--- /Solver.cpp Sat May 25 21:24:58 2013 UTC
+++ /Solver.cpp Mon May 27 18:25:38 2013 UTC
@@ -457,6 +457,9 @@
}

DistrictSet* Solver::getDistricts() { // lazy allocating caching accessor
+ if (_dists != NULL) {
+ return _dists;
+ }
if ( districtSetFactory != NULL ) {
_dists = districtSetFactory(this);
} else {

==============================================================================
Revision: 16bdfe1329b7
Branch: default
Author: Brian Olson <brian...@gmail.com>
Date: Mon May 27 20:48:08 2013 UTC
Log: a bunch of work on new results page in django template with
current vs my results
http://code.google.com/p/redistricter/source/detail?r=16bdfe1329b7

Added:
/djangotemplates.py
/html/st_index_django.html
Modified:
/analyze_submissions.py
/measurerace.py
/notes.txt
/render_2013_actual.py
/states.py

=======================================
--- /dev/null
+++ /djangotemplates.py Mon May 27 20:48:08 2013 UTC
@@ -0,0 +1,26 @@
+#!/usr/bin/python
+
+import os
+
+import django
+import django.template
+import django.template.loader as tload
+
+# django settings
+TEMPLATE_LOADERS = ('django.template.loaders.filesystem.Loader',)
+TEMPLATE_DIRS = (
+ os.path.join(os.path.dirname(__file__), 'html'),
+ os.path.dirname(__file__))
+TEMPLATE_DEBUG = True
+SECRET_KEY = 'aoeuaoeuaoeu'
+
+os.environ['DJANGO_SETTINGS_MODULE'] = __name__
+#tload.settings = sys.modules[__name__]
+
+def render(templateName, contextDict):
+ tt = tload.get_template(templateName)
+ context = django.template.Context(contextDict)
+ renderout = tt.render(context)
+ ## TODO: unicode instead of str, better wsgi containers fix this?
+ ustr = unicode(renderout)
+ return ustr.encode('utf-8')
=======================================
--- /dev/null
+++ /html/st_index_django.html Mon May 27 20:48:08 2013 UTC
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html><head><title>{{statename}} Redistricting</title>
+<link href="{{rooturl}}report.css" rel="stylesheet" type="text/css" />
+<style>#custom-tweet-button a {padding: 2px 5px 2px 20px;background:
url('{{rooturl}}tweet.ico') 1px center
no-repeat;text-decoration:none;}</style>
+</head>
+<body bgcolor="#ffffff">
+<div style="float:right;width:20em;">
+
+</div>
+<h1>{{statename}} Redistricting</h1>
+<div class="small">From 2010 data</div>
+<table class="sp"><tr><td>
+<div><a href="/2010/">2010 Redistricting Home</a></div>
+{{statenav|safe}}
+<hr width="50%" align="center">
+<div id="sociald">{{social|safe}}</div>
+</td><td>
+
+<table id="imt"><tr><td align="center"><a href="{{ba_large}}"><img
src="{{ba_small}}" title="{{statename}} congressional district map, current
and my way" alt="{{statename}} congressional district map, current and my
way"></a></td>{% if current_small %}<td align="center"><a
href="{{current_large}}"><img src="{{current_small}}"></a></td>{%
endif %}</tr>
+<tr><td align="center">{{statename}} possible district map from my
solver.<br /><a href="{{ba_large}}" title="{{statename}} congressional
district map, current and my way">Larger {{statename}} map</a></td>{% if
current_small %}<td align="center">{{statename}} current district map<br
/><a href="{{current_large}}">Larger {{statename}} map</a></td>{%
endif %}</tr>
+</table>
+<table
+<tr>
+{% if current_kmpp %}<td></td>{% endif %}
+<td class="myoh">average distance between a voter and<br />the center of
their district (in kilometers)</td><td class="myoh">difference in
population between<br />the least populous district and<br />the most
populous district<!-- (out of about {{avgpop}})--></td><td
class="myoh">standard deviation of<br />district populations</td></tr>
+{% if current_kmpp %}
+<tr><td class="myow">Current&nbsp;map</td><td
class="myon">{{current_kmpp}}</td><td
class="myon">{{current_spread}}</td><td
class="myon">{{current_std}}</td></tr>
+{% endif %}
+<tr>{% if current_kmpp %}<td class="myow">My&nbsp;map</td>{% endif %}<td
class="myon">{{my_kmpp}}</td><td class="myon">{{my_spread}}</td><td
class="myon">{{my_std}}</td></tr></table>
+{{extra|safe}}
+{% if current_demographics %}
+<table><tr><th colspan="2">Demographics</th><tr>
+<tr><th>Current</th><th>My Way</th></tr>
+<tr><td>{{current_demographics|safe}}</td><td>{{racedata|safe}}</td></tr>
+</table>
+{% else %}
+{{racedata|safe}}
+{% endif %}
+<div><a href="solution.zip">zipped csv block list for
{{statename}}</a></div>
+<div><a href="/2000/{{stu}}/">{{statename}} from 2000 Census</a></div>
+</td></tr></table>
+<p><a rel="license"
href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative
Commons License" style="border-width:0"
src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a><br />This
work by <a xmlns:cc="http://creativecommons.org/ns#"
href="http://bdistricting.com/" property="cc:attributionName"
rel="cc:attributionURL">Brian Olson</a> is licensed under a <a
rel="license"
href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons
Attribution-ShareAlike 3.0 Unported License</a>.</p>
+{{google_analytics|safe}}
+</body></html>
=======================================
--- /analyze_submissions.py Sat May 25 21:24:58 2013 UTC
+++ /analyze_submissions.py Mon May 27 20:48:08 2013 UTC
@@ -17,14 +17,14 @@
import urllib
import zipfile

+import djangotemplates
from kmppspreadplot import svgplotter
-from newerthan import newerthan
+from newerthan import newerthan, any_newerthan
import resultspage
import runallstates
import states

srcdir_ = os.path.dirname(os.path.abspath(__file__))
-legpath_ = os.path.join(srcdir_, 'legislatures.csv')

_resources = ('report.css', 'tweet.ico', 'spreddit7.gif')

@@ -136,6 +136,24 @@
return string.Template(cooked)


+_analyze_re =
re.compile(r'.*?([0-9.]+)\s+Km/person.*avg=([0-9.]+).*std=([0-9.]+).*max=([0-9.]+).*min=([0-9.]+).*median=([0-9.]+).*',
re.MULTILINE|re.DOTALL)
+
+
+def parseAnalyzeStats(rawblob):
+ """Return (kmpp, spread, std)"""
+ # e.g.:
+ #generation 0: 38.093901615 Km/person
+ #population avg=696345 std=0.395847391
+ #max=696345 (dist# 1) min=696344 (dist# 8) median=696345 (dist# 14)
+ m = _analyze_re.match(rawblob)
+ logging.debug('groups=%r', m.groups())
+ kmpp = float(m.group(1))
+ std = float(m.group(3))
+ maxp = float(m.group(4))
+ minp = float(m.group(5))
+ return (kmpp, maxp - minp, std)
+
+
# Example analyze output:
# generation 0: 21.679798418 Km/person
# population avg=634910 std=1707.11778
@@ -146,6 +164,7 @@


def measure_race(stl, numd, pbfile, solution, htmlout, zipname,
exportpath=None, bindir=None, printcmd=None):
+ """Writes html to htmlout. Returns blob of text with stats. Pass blob to
parseAnalyzeStats if desired."""
if not os.path.exists(zipname):
logging.error('could not measure race without %s', zipname)
return
@@ -165,10 +184,84 @@

if printcmd:
printcmd(cmd)
- p = subprocess.Popen(cmd, shell=False, stdin=subprocess.PIPE)
+ p = subprocess.Popen(cmd, shell=False, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
p.stdin.write(zf.read(part1name))
p.stdin.close()
p.wait()
+ analyze_text = p.stdout.read()
+ return analyze_text
+
+
+def getStatesCsvSources(actualsDir):
+ """For directory of 00_XX_*.txt return map {stu, source csv filename}"""
+ stDistFiles = {}
+ anyError = False
+
+ distdirall = os.listdir(actualsDir)
+
+ statefileRawRe = re.compile('.._(..)_.*\.txt', re.IGNORECASE)
+
+ for fname in distdirall:
+ m = statefileRawRe.match(fname)
+ if m:
+ stu = m.group(1).upper()
+ if states.nameForPostalCode(stu) is not None:
+ # winner
+ old = stDistFiles.get(stu)
+ if old is None:
+ stDistFiles[stu] = fname
+ else:
+ logging.error('collision %s -> %s AND %s', stu, old, fname)
+ anyError = True
+
+ return stDistFiles, anyError
+
+
+def noSource(sourceName):
+ logging.error('missing source %s', sourceName)
+
+
+def processActualsSource(actualsDir, stu, sourceCsvFname, pb, mppb,
zipname):
+ """process 00_XX_SLDU.txt into intermediate XX.csv, output
{XX.png,xx.html,xx_stats.txt}
+ return (kmpp, spread, std)
+ """
+ stl = stu.lower()
+
+ # actuals block source and intermediate csv
+ csvpath = os.path.join(actualsDir, sourceCsvFname)
+ simplecsvpath = os.path.join(actualsDir, stu + '.csv')
+
+ # output html and png
+ htmlout = os.path.join(actualsDir, stl + '.html')
+ pngout = os.path.join(actualsDir, stu + '.png')
+ png500out = os.path.join(actualsDir, stu + '500.png')
+ analyzeout = os.path.join(actualsDir, stl + '_stats.txt')
+ analyzeText = None
+
+ if any_newerthan( (pb, mppb, csvpath, zipname), (pngout, png500out,
htmlout, analyzeout), noSourceCallback=noSource):
+ if newerthan(csvpath, simplecsvpath):
+ csvToSimpleCsv(csvpath, simplecsvpath)
+ if any_newerthan( (pb, mppb, simplecsvpath), pngout):
+ cmd = [drendpath(), '-d=-1', '-P', pb, '--mppb',
mppb, '--csv-solution', simplecsvpath, '--pngout', pngout]
+ logging.info('%r', cmd)
+ p = subprocess.Popen(cmd, stdin=None, stdout=subprocess.PIPE,
shell=False)
+ retcode = p.wait()
+ if retcode != 0:
+ logging.error('cmd `%s` retcode %s log %s', cmd, retcode,
p.stdout.read())
+ sys.exit(1)
+ if any_newerthan( (pb, mppb, simplecsvpath, zipname), (htmlout,
analyzeout)):
+ analyzeText = measure_race(stl, '-1', pb, simplecsvpath, htmlout,
zipname, printcmd=lambda x: logging.info('%r', x))
+ atout = open(analyzeout, 'w')
+ atout.write(analyzeText)
+ atout.close()
+ if newerthan(pngout, png500out):
+ subprocess.call(['convert', pngout, '-resize', '500x500', png500out])
+
+ if analyzeText is None:
+ atin = open(analyzeout, 'r')
+ analyzeText = atin.read()
+ atin.close()
+ return parseAnalyzeStats(analyzeText)


def loadDatadirConfigurations(configs, datadir, statearglist=None,
configPathFilter=None):
@@ -219,6 +312,15 @@
self.socialTemplate = None
# cache for often used self.statenav(None, configs)
self._statenav_all = None
+ self._actualsMaps = {}
+
+ def actualsSource(self, actualSet, stu):
+ """Lazy loading accessor to find source CSV files for
actualsdir/{set}/??_{stu}_*.txt"""
+ maps = self._actualsMaps.get(actualSet)
+ if maps is None:
+ maps, _ = getStatesCsvSources(os.path.join(self.options.actualdir,
actualSet))
+ self._actualsMaps[actualSet] = maps
+ return maps[stu]

def getPageTemplate(self, rootdir=None):
if self.pageTemplate is None:
@@ -459,15 +561,18 @@
if configs is None:
configs = self.getBestConfigs()
newestconfig = self.newestWinner(configs)
- clist = configs.keys()
- clist.sort()
+
+ # TODO: django templates?
out = open(outpath, 'w')
out.write("""<!doctype html>
<html><head><title>solution report</title><link rel="stylesheet"
href="report.css" /></head><body><h1>solution report</h1><p
class="gentime">Generated %s</p>
""" % (localtime(),))
out.write("""<div style="float:left"><div></div>""" +
self.statenav(None, configs) + """</div>\n""")
out.write("""<p>Newest winning result: <a href="%s/">%s</a><br /><img
src="%s/map500.png"></p>\n""" % (newestconfig['config'],
newestconfig['config'], newestconfig['config']))
+
firstNoSolution = True
+ clist = configs.keys()
+ clist.sort()
for cname in clist:
data = configs[cname]
if not data['kmpp']:
@@ -494,9 +599,9 @@
args = dict(self.config[cname].drendargs)
args['--pngout'] = pngpath
if dszpath:
- args['--loadSolution'] = dszpath
+ args['-r'] = dszpath
elif solutionDszRaw:
- args['--loadSolution'] = '-'
+ args['-r'] = '-'
else:
self.stderr.write('error: need dsz or raw dsz bytes for doDrend\n')
return None
@@ -697,6 +802,7 @@
if self.options.configlist and (cname not in self.options.configlist):
logging.debug('skipping %s not in configlist', cname)
return
+ stl = stu.lower()
outdir = self.options.outdir
sdir = os.path.join(outdir, cname, str(data['id']))
if not os.path.isdir(sdir):
@@ -712,6 +818,12 @@

tpath = self.cleanupSolutionPath(data['path'])
tfparts = extractSome(tpath, ('solution', 'statsum'))
+ actualMapPath = None
+ actualMap500Path = None
+ actualHtmlPath = None
+ current_kmpp = None
+ current_spread = None
+ current_std = None

if 'solution' in tfparts:
# write solution.dsz
@@ -753,6 +865,19 @@
map500path = os.path.join(sdir, 'map500.png')
if newerthan(mappath, map500path):
subprocess.call(['convert', mappath, '-resize', '500x500', map500path])
+
+ # use actual maps if available
+ if self.options.actualdir:
+ # ensure setup
+ actualSet = states.stateConfigToActual(stu, cname.split('_',1)[1])
+ config = self.config[cname]
+ drendargs = config.drendargs
+ zipname = os.path.join(config.datadir, 'zips', stl + '2010.pl.zip')
+ (current_kmpp, current_spread, current_std) =
processActualsSource(os.path.join(self.options.actualdir, actualSet), stu,
self.actualsSource(actualSet, stu), drendargs['-P'], drendargs['--mppb'],
zipname)
+
+ actualMapPath = os.path.join(self.options.actualdir, actualSet, stu
+ '.png')
+ actualMap500Path = os.path.join(self.options.actualdir, actualSet, stu
+ '500.png')
+ actualHtmlPath = os.path.join(self.options.actualdir, actualSet, stl
+ '.html')
else:
logging.error('no solution for %s', cname)
self.processFailedSubmissions(configs, cname)
@@ -766,8 +891,8 @@
permalink = os.path.join(self.options.rooturl, cname, str(data['id']))
+ '/'
racedata = ''
if os.path.exists(racehtml):
- racedata = '<h3>Population Race Breakdown Per District</h3>'
- racedata += open(racehtml, 'r').read()
+ #racedata = '<h3>Population Race Breakdown Per District</h3>' +
+ racedata = open(racehtml, 'r').read()
extrapath = os.path.join(outdir, cname, 'extra.html')
extrahtml = ''
if os.path.exists(extrapath):
@@ -776,20 +901,26 @@
pageabsurl = urljoin(self.options.siteurl, self.options.rooturl, cname)
+ '/'
cgipageabsurl = urllib.quote_plus(pageabsurl)
cgiimageurl = urllib.quote_plus(urljoin(self.options.siteurl,
self.options.rooturl, cname, 'map500.png'))
+ actualHtmlData = None
+ if actualHtmlPath:
+ ahin = open(actualHtmlPath, 'rb')
+ actualHtmlData = ahin.read()
+ ahin.close

- st_template = self.getPageTemplate()
- out = open(ihpath, 'w')
- out.write(st_template.substitute(
+ context = dict(
statename=statename,
stu=stu,
statenav=self.statenav(cname, configs),
ba_large='map.png',
ba_small='map500.png',
+ current_large=actualMapPath,
+ current_small=actualMap500Path,
+ current_demographics=actualHtmlData,
# TODO: get avgpop for state
avgpop='',
- current_kmpp='',
- current_spread='',
- current_std='',
+ current_kmpp=current_kmpp,
+ current_spread=current_spread,
+ current_std=current_std,
my_kmpp=str(kmpp),
my_spread=str(int(float(spread))),
my_std=str(std),
@@ -800,7 +931,20 @@
cgiimageurl=cgiimageurl,
google_analytics=_google_analytics(),
social=self.getSocial(pageabsurl, cgipageabsurl),
- ))
+ )
+ if actualMapPath and actualMap500Path:
+ context['current_large'] = stu + '.png'
+ context['current_small'] = stu + '500.png'
+ atomicLink(actualMapPath, os.path.join(sdir, stu + '.png'))
+ atomicLink(actualMap500Path, os.path.join(sdir, stu + '500.png'))
+ atomicLink(actualMapPath, os.path.join(outdir, cname, stu + '.png'))
+ atomicLink(actualMap500Path, os.path.join(outdir, cname, stu
+ '500.png'))
+ out = open(ihpath, 'w')
+ if False:
+ st_template = self.getPageTemplate()
+ out.write(st_template.substitute(**context))
+ else:
+ out.write(djangotemplates.render('st_index_django.html', context))
out.close()
for x in
('map.png', 'map500.png', 'index.html', 'solution.dsz', 'solution.csv.gz', 'solution.zip'):
atomicLink(os.path.join(sdir, x), os.path.join(outdir, cname, x))
@@ -877,6 +1021,7 @@
argp.add_option('--redraw', dest='redraw', action='store_true',
default=False)
argp.add_option('--rehtml', dest='rehtml', action='store_true',
default=False)
argp.add_option('--config', dest='configlist', action='append',
default=[])
+ argp.add_option('--actuals', dest='actualdir', default=None,
help='contains /{cd,sldu,sldl}')
(options, args) = argp.parse_args()
if options.verbose:
logging.getLogger().setLevel(logging.DEBUG)
=======================================
--- /measurerace.py Mon Jul 20 14:13:54 2009 UTC
+++ /measurerace.py Mon May 27 20:48:08 2013 UTC
@@ -1,7 +1,8 @@
#!/usr/bin/python


-"""Create html tables for simple race breakdown per district.
+"""Measure race demographics for 2000 census and 109th Congress.
[DEPRECATED]
+Create html tables for simple race breakdown per district.
Requires '00001' census data files,
typically 'data/XX/zips/xx00001_uf1.zip'
which can be fetched by 'setupstatedata.py --getextra=00001
"""
=======================================
--- /notes.txt Sat May 25 21:24:58 2013 UTC
+++ /notes.txt Mon May 27 20:48:08 2013 UTC
@@ -209,3 +209,8 @@
~/src/redistricter/render_2013_actual.py
--datadir=/Volumes/bulktogo/redata/2010
--districtdir=/Volumes/bulktogo/redata/2010/2013_actual/sldu
~/src/redistricter/render_2013_actual.py
--datadir=/Volumes/bulktogo/redata/2010
--districtdir=/Volumes/bulktogo/redata/2010/2013_actual/sldl

+t
+
+~/src/redistricter/analyze -P FL/fl.pb -d=-1
--csv-solution=2013_actual/cd/12_FL_CD113.txt
--compare :5,7,8,9,10,11,12,13 --labels
total,white,black,native,asian,pacific,other,mixed --dsort 1 --html
/tmp/fl.html --notext
+
+~/src/redistricter/analyze_submissions.py
--actuals=/Volumes/bulktogo/redata/2010/2013_actual
--datadir=/Volumes/bulktogo/redata/2010
--soldir=/Volumes/bulktogo/redata/2010/solutions
--report=/Volumes/bulktogo/redata/2010/solutions/report/report.html
--outdir=/Volumes/bulktogo/redata/2010/solutions/report --rooturl=/2010/
--rehtml --config=FL_Congress
=======================================
--- /render_2013_actual.py Sat May 25 21:24:58 2013 UTC
+++ /render_2013_actual.py Mon May 27 20:48:08 2013 UTC
@@ -16,7 +16,7 @@
import sys


-from analyze_submissions import measure_race
+from analyze_submissions import getStatesCsvSources, processActualsSource
from newerthan import newerthan, any_newerthan
import states

@@ -49,6 +49,21 @@
fout.close()


+_drendpath = None
+
+
+def drendpath():
+ global _drendpath
+ if _drendpath is None:
+ _drendpath = os.path.join(srcdir_, 'drend')
+ if not os.path.exists(_drendpath):
+ logging.error('no drend binary at %r', drendpath)
+ sys.exit(1)
+ return _drendpath
+
+
+
+
def main():
srcdir_ = os.path.dirname(os.path.abspath(__file__))

@@ -58,66 +73,24 @@

options, args = op.parse_args()

- stDistFiles = {}
- anyError = False
-
- distdirall = os.listdir(options.distdir)
-
- statefileRawRe = re.compile('.._(..)_.*\.txt', re.IGNORECASE)
-
- for fname in distdirall:
- m = statefileRawRe.match(fname)
- if m:
- stu = m.group(1).upper()
- if states.nameForPostalCode(stu) is not None:
- # winner
- old = stDistFiles.get(stu)
- if old is None:
- stDistFiles[stu] = fname
- else:
- logging.error('collision %s -> %s AND %s', stu, old, fname)
- anyError = True
-
+ stDistFiles, anyError = getStatesCsvSources(options.distdir)
#for k,v in stDistFiles.iteritems():
# print '%s\t%s' % (k, v)

if anyError:
sys.exit(1)

- drendpath = os.path.join(srcdir_, 'drend')
- if not os.path.exists(drendpath):
- logging.error('no drend binary at %r', drendpath)
- sys.exit(1)
-
- def noSource(sourceName):
- logging.error('missing source %s', sourceName)
+ for stu, sourceCsvFname in stDistFiles.iteritems():
+ print stu
+ stl = stu.lower()

- for k,v in stDistFiles.iteritems():
- print k
- stl = k.lower()
- stu = k.upper()
- csvpath = os.path.join(options.distdir, v)
- simplecsvpath = os.path.join(options.distdir, stu + '.csv')
+ # common datadir inputs
stdir = os.path.join(options.datadir, stu)
pb = os.path.join(stdir, stl + '.pb')
mppb = os.path.join(stdir, stu + '.mppb')
zipname = os.path.join(stdir, 'zips', stl + '2010.pl.zip')
- htmlout = os.path.join(stu + '.html')
- pngout = stu + '.png'
- if any_newerthan( (pb, mppb, csvpath, zipname), (pngout, htmlout),
noSourceCallback=noSource):
- if newerthan(csvpath, simplecsvpath):
- csvToSimpleCsv(csvpath, simplecsvpath)
- if any_newerthan( (pb, mppb, simplecsvpath), pngout):
- cmd = [drendpath, '-d=-1', '-P', pb, '--mppb',
mppb, '--csv-solution', simplecsvpath, '--pngout', pngout]
- print ' '.join(cmd)
- p = subprocess.Popen(cmd, stdin=None, stdout=subprocess.PIPE,
shell=False)
- retcode = p.wait()
- if retcode != 0:
- logging.error('cmd `%s` retcode %s log %s', cmd, retcode,
p.stdout.read())
- sys.exit(1)
- if any_newerthan( (pb, mppb, simplecsvpath, zipname), htmlout):
- measure_race(stl, '-1', pb, simplecsvpath, htmlout, zipname,
printcmd=lambda x: sys.stderr.write(' '.join(x) + '\n'))

+ processActualsSource(options.distdir, stu, sourceCsvFname, pb, mppb,
zipname)


if __name__ == '__main__':
=======================================
--- /states.py Sun Feb 27 20:50:04 2011 UTC
+++ /states.py Mon May 27 20:48:08 2013 UTC
@@ -68,8 +68,9 @@

def codeForState(stateName):
"""Return two letter postal code for proper Name (case sensitive)."""
+ snl = stateName.lower()
for x in states:
- if x[0] == stateName:
+ if x[0].lower() == snl:
return x[1]
return None

@@ -116,6 +117,12 @@
self.code = code
self.count = count

+ def __str__(self):
+ return '%s "%s" (%s): %s' % (self.code, self.name, self.shortname,
self.count)
+
+ def __repr__(self):
+ return 'LegislatureStat(%r, %r, %r, %r)' % (self.name, self.shortname,
self.code, self.count)
+
def legislatureStatsForPostalCode(code):
"""Return [LegislatureStat, ...].
Returns None if code is bogus."""
@@ -146,3 +153,29 @@
if ls.shortname == name:
return ls.name
return name
+
+
+def stateConfigToActual(stu, configname):
+ """Map ('MA','Senate') to 'sldu' (or 'cd' or 'sldl' as appropriate)"""
+ if configname == 'Congress':
+ return 'cd'
+ ls = legislatureStatsForPostalCode(stu)
+ if ls is None:
+ return None
+ minseats = None
+ confseats = None
+ for tls in ls:
+ if tls.shortname == 'Congress':
+ continue
+ if (minseats is None) or (tls.count < minseats):
+ minseats = tls.count
+ if tls.shortname == configname:
+ confseats = tls.count
+ if confseats is None:
+ raise Exception('unknown configuration %s,%s' % (stu, configname))
+ if confseats == minseats:
+ # the body with fewer seats is the 'upper' house of legislature
+ # Also, Nebraska.
+ return 'sldu'
+ else:
+ return 'sldl'

==============================================================================
Revision: c03009c1b360
Branch: default
Author: Brian Olson <brian...@gmail.com>
Date: Mon May 20 15:23:00 2013 UTC
Log: move census 2000 results to /2000/ on website
http://code.google.com/p/redistricter/source/detail?r=c03009c1b360

Modified:
/result_index_pyt.html

=======================================
--- /result_index_pyt.html Sun Jun 3 05:34:32 2012 UTC
+++ /result_index_pyt.html Mon May 20 15:23:00 2013 UTC
@@ -27,7 +27,7 @@
<div class="rb"><a href="/about.html#election">Other Election Reform
Issues</a></div>
<div class="rb"><a href="/author.html">About the Author</a></div>
<div class="rb"><a href="/about.html#open">Open Source</a></div>
-<div class="rb"><a href="/">Census 2000 Based Compact
Redistricting</a></div>
+<div class="rb"><a href="/2000/">Census 2000 Based Compact
Redistricting</a></div>

</td><td align="center"><div>Newest winning result: <a
href="${nwinner}/">${nwinnername}</a></div><div><a href="${nwinner}/"><img
src="${nwinner}/map500.png"></a></div></td></tr></table>


==============================================================================
Revision: dfa2a0a5229c
Branch: default
Author: Brian Olson <brian...@gmail.com>
Date: Mon May 27 21:24:51 2013 UTC
Log: hg merge
http://code.google.com/p/redistricter/source/detail?r=dfa2a0a5229c


Reply all
Reply to author
Forward
0 new messages