Along the Edge of Lake
Parts of the lake where not super-marshy, but perfect for the growing of tall Timothy Grasses along the shoreline.
Taken on Sunday August 29, 2010 at Balsam Lake Mountain Wild Forest.Why ads? π€ / Privacy Policy π³
Parts of the lake where not super-marshy, but perfect for the growing of tall Timothy Grasses along the shoreline.
Taken on Sunday August 29, 2010 at Balsam Lake Mountain Wild Forest.Nice view.
Taken on Saturday August 24, 2013 at Mine Kill State Park.Real Property Tax Law 1590 requires that municipalities post their tax rolls, within 10 days of the proposed and final rolls being approved. Below is an PHP script that will extract the reports into a CSV file for importing into Microsoft Excel or a GIS program. It extracts the text from the PDF using pdftotext
from the poppler-util
.
If you do not want to install poppler-util
, I would encourage to check out the simpler and better maintained R Script for for Converting RPTL 1590 Reports that I also wrote. Both versions can also be found on my GitHub.
<?php
// this program requires pdftotext (a linux program) and PHP version 7.2
// first convert PDF to text
$pdfdir = "input-pdf";
$textdir = "output-txt";
// delete old input-text
if (isset($argv[1]) && $argv[1] == 'delete') {
echo "Deleting old conversions ...\n";
system("rm $textdir/*");
}
foreach (scandir($pdfdir) as $file) {
if (substr($file, -4) !== '.pdf') {
continue;
}
$textfile = substr($file, 0, -4).".txt";
$town = substr($file, 0, -4);
echo ("#### START $town #### \n");
if (file_exists("$textdir/$textfile")) {
echo "Text file exists, not converting PDF again (arg[1] == delete to override).\n";
}
else {
echo "Converting to text file ...";
system('pdftotext -layout '.escapeshellarg("$pdfdir/$file").' '.escapeshellarg("$textdir/$textfile"));
echo " DONE\n";
}
$text = file("$textdir/$textfile");
$town = substr($file, 0, -4);
$taxroll = array();
$payerId = 0;
$output = "";
$townId = "";
$swisId = "";
$countyId = "";
$villageId = "";
for ($i = 0; $i < count($text); $i++) {
if ($i % 100 == 0) echo "#";
// capture county - town - swis
if (preg_match('/COUNTY\s*?- (.*?)\s{2}/', $text[$i], $matches)) $countyId = $matches[1];
if (preg_match('/CITY\s*?- (.*?)\s{2}/', $text[$i], $matches)) $townId = $matches[1];
if (preg_match('/TOWN\s*?- (.*?)\s{2}/', $text[$i], $matches)) $townId = $matches[1];
if (preg_match('/VILLAGE\s*?- (.*?)\s{2}/', $text[$i], $matches)) $villageId = $matches[1];
if (preg_match('/SWIS\s*?- (.*?)\s{2}/', $text[$i], $matches)) $swisId = $matches[1];
// first line = tax id
$pattern = '/\*{3,} ((\d|\-|\.){4,}) \*{3,}/';
preg_match($pattern, $text[$i], $matches);
// we've found the start of a new tax record!
if (isset($matches[1])) {
$i++;
$taxpayer = array();
$j = 0;
// output each part onto the line
while (isset($text[$i]) && !preg_match('/\*{3,}/', $text[$i])) {
$split = preg_split('/\s{2,}/', $text[$i]);
$taxpayer[$j] = $split;
$i++; $j++;
}
$taxpayer[$j] = array('location',$countyId, $townId, $villageId, $swisId);
$taxroll[$payerId++] = $taxpayer;
$i--;
}
}
// export unprocess tax rolls for debug
file_put_contents("output-debug/$town.txt", print_r($taxroll,true));
// next scan for all special district types in file
$specialDistType = array();
foreach ($taxroll as $taxpayer) {
for ($i = 0; $i < count($taxpayer); $i++) {
for ($j = 0; $j < count($taxpayer[$i]); $j++) {
if (preg_match('/^([A-Z]{2})(\d\d\d) (.*?)( TO|$|\d{2,})/', $taxpayer[$i][$j],$matches)) {
$specialDistType[$matches[1]] = $matches[1];
}
}
}
}
ksort($specialDistType);
// then process into a nice field
$formTax = array();
foreach ($taxroll as $taxpayer) {
$formPayer = array();
$formPayer[0] = $taxpayer[1][0]; // tax id
if (isset($taxpayer[0][1]) && preg_match('/^(\d.*?) (.*?)$/',$taxpayer[0][1], $address)) {
$formPayer[1] = $address[1]; // street number
$formPayer[2] = ucwords(strtolower($address[2])); // street name
}
elseif (isset($taxpayer[0][1])) {
$formPayer[1] = '';
$formPayer[2] = ucwords(strtolower($taxpayer[0][1])); // street name
}
if (isset($formPayer[1])) $formPayer[23] = ltrim($formPayer[1].' '.$formPayer[2]); // full street
else if (isset($formPayer[1])) $formPayer[23] = ltrim($formPayer[2]);
$formPayer[3] = ucwords(strtolower($taxpayer[2][0])); // owner 1
// next five lines are either are owner or address info
for ($i = 3; $i < 8; $i++) {
if (!isset($taxpayer[$i][0])) continue;
// if a taxpayer name
if (preg_match('/^[A-Z]/',$taxpayer[$i][0]) && !preg_match('/^PO/',$taxpayer[$i][0]) && !preg_match('/^(.*?), (\w\w) (.*?)$/',$taxpayer[$i][0])) {
if (!isset($formPayer[4])) $formPayer[4] = ucwords(strtolower($taxpayer[$i][0]));
else if (!isset($formPayer[5])) $formPayer[5] = ucwords(strtolower($taxpayer[$i][0]));
else if (!isset($formPayer[6])) $formPayer[6] = ucwords(strtolower($taxpayer[$i][0]));
}
// if a city - state - zip
else if (preg_match('/^(.*?), (\w\w) (.*?)$/',$taxpayer[$i][0], $address)) {
$formPayer[10] = ucwords(strtolower($address[1]));
$formPayer[11] = strtoupper($address[2]);
$formPayer[12] = ucwords(strtolower($address[3]));
}
// if an address (pad to this field)
else if (preg_match('/^\d/',$taxpayer[$i][0]) || preg_match('/^PO/',$taxpayer[$i][0])) {
if (!isset($formPayer[7])) $formPayer[7] = ucwords(strtolower($taxpayer[$i][0]));
else if (!isset($formPayer[8])) $formPayer[8] = ucwords(strtolower($taxpayer[$i][0]));
else if (!isset($formPayer[9])) $formPayer[9] = ucwords(strtolower($taxpayer[$i][0]));
}
$formPayer[13] = $taxpayer[1][1];
}
// extract coordinates by searching through array
for ($i = 0; $i < count($taxpayer); $i++) {
for ($j = 0; $j < count($taxpayer[$i]); $j++) {
if (preg_match('/EAST-(\d*) NRTH-(\d*)/', $taxpayer[$i][$j], $coord)) {
$formPayer[14] = $coord[1];
$formPayer[15] = $coord[2];
}
}
}
// extract acres
for ($i = 0; $i < count($taxpayer); $i++) {
for ($j = 0; $j < count($taxpayer[$i]); $j++) {
if (preg_match('/ACRES *?(\d+)/', $taxpayer[$i][$j],$acres)) {
$formPayer[16] = $acres[1];
}
else if (preg_match('/ACRES/', $taxpayer[$i][$j])) {
if (preg_match('/^([0-9.]+)/', $taxpayer[$i][$j+1], $acres)) $formPayer[16] = $acres[1];
}
}
}
// extract full market value
for ($i = 0; $i < count($taxpayer); $i++) {
for ($j = 0; $j < count($taxpayer[$i]); $j++) {
if (preg_match('/FULL MARKET VALUE *?(\d+)/', $taxpayer[$i][$j],$value)) {
$formPayer[17] = str_replace(',','',$value[1]);
}
else if (preg_match('/FULL MARKET VALUE/', $taxpayer[$i][$j])) {
if (preg_match('/^([0-9,]+)/', $taxpayer[$i][$j+1], $value)) $formPayer[17] = str_replace(',','',$value[1]);
}
}
}
// extract deed book info
for ($i = 0; $i < count($taxpayer); $i++) {
for ($j = 0; $j < count($taxpayer[$i]); $j++) {
if (preg_match('/DEED BOOK *?(\d+) *?PG-(\d+)/', $taxpayer[$i][$j],$value)) {
$formPayer[18] = $value[1];
$formPayer[19] = $value[2];
}
else if (preg_match('/DEED BOOK *?(\d+)/', $taxpayer[$i][$j],$value)) {
$formPayer[18] = $value[1];
if (isset($taxpayer[$i][$j+1]) && preg_match('/^PG-(\d+)/', $taxpayer[$i][$j+1], $value)) $formPayer[19] = $value[1];
}
}
}
// county taxable amount
for ($i = 0; $i < count($taxpayer); $i++) {
for ($j = 0; $j < count($taxpayer[$i]); $j++) {
if (preg_match('/COUNTY TAXABLE VALUE/', $taxpayer[$i][$j])) $formPayer[20] = chop(str_replace(',','',$taxpayer[$i][$j+1]));
}
}
// school taxable amount
for ($i = 0; $i < count($taxpayer); $i++) {
for ($j = 0; $j < count($taxpayer[$i]); $j++) {
if (preg_match('/SCHOOL TAXABLE VALUE/', $taxpayer[$i][$j])) $formPayer[21] = chop(str_replace(',','',$taxpayer[$i][$j+1]));
}
}
// city taxable amount
for ($i = 0; $i < count($taxpayer); $i++) {
for ($j = 0; $j < count($taxpayer[$i]); $j++) {
if (isset($taxpayer[$i][$j]) && preg_match('/^(CITY|TOWN)/', $taxpayer[$i][$j])) {
if (isset($taxpayer[$i][$j+1]) && preg_match('/^TAXABLE VALUE/', $taxpayer[$i][$j+1])) $formPayer[22] = chop(str_replace(',','',$taxpayer[$i][$j+2]));
}
}
}
// field relating to solar power (for munis that have such laws)
$formPayer[24] = '';
for ($i = 0; $i < count($taxpayer); $i++) {
for ($j = 0; $j < count($taxpayer[$i]); $j++) {
if (preg_match('/solar/i', $taxpayer[$i][$j])) {
$formPayer[24] .= "{$taxpayer[$i][$j]},";
}
}
}
// STAR
$formPayer[25] = '';
for ($i = 0; $i < count($taxpayer); $i++) {
for ($j = 0; $j < count($taxpayer[$i]); $j++) {
if (preg_match('/ STAR/', $taxpayer[$i][$j])) {
$formPayer[25] .= "{$taxpayer[$i][$j]},";
}
}
}
// STAR
$formPayer[26] = '';
for ($i = 0; $i < count($taxpayer); $i++) {
for ($j = 0; $j < count($taxpayer[$i]); $j++) {
if (preg_match('/(VET WAR|CW_15_VET|VETWAR|VETDIS|VETERANS)/', $taxpayer[$i][$j])) {
$formPayer[26] .= "{$taxpayer[$i][$j]},";
}
}
}
// SCHOOL
$formPayer[27] = $taxpayer[2][1];
// columns 28+ are special districts
$l = 28;
foreach ($specialDistType as $type) {
$formPayer[$l] = '';
for ($i = 0; $i < count($taxpayer); $i++) {
for ($j = 0; $j < count($taxpayer[$i]); $j++) {
if (isset($taxpayer[$i][$j]) && preg_match('/^(\w\w)(\d\d\d) (.*?)( TO|$|\d{2,})/', $taxpayer[$i][$j],$matches)) {
if ($matches[1] == $type) $formPayer[$l] .= "{$matches[1]}{$matches[2]} {$matches[3]} ";
}
}
}
$l++;
}
// sort and add missing keys
for ($i = 0; $i < count($formPayer); $i++) {
if (!isset($formPayer[$i])) $formPayer[$i] = '';
}
ksort($formPayer);
// shift onto the rolls county, town, village, swis
for ($i = 0; $i < count($taxpayer); $i++) {
if ($taxpayer[$i][0] != 'location') continue;
// add array to line
for ($j = count($taxpayer[$i])-1; $j > 0; $j--) array_unshift($formPayer, $taxpayer[$i][$j]);
}
$formTax[] = $formPayer;
}
// lastly sort form by street and number
$addNum = array();
$addSt = array();
$own1 = array();
for ($i = 0; $i < count($formTax); $i++) {
$addSt[] = $formTax[$i][6];
$addNum[] = $formTax[$i][5];
$own1[] = $formTax[$i][7];
}
// now apply sort
array_multisort($addSt, SORT_ASC,
$addNum, SORT_NUMERIC, SORT_ASC,
$own1, SORT_ASC,
$formTax);
//print_r($formTax);
echo "\nWriting to CSV ...";
// print out form
$output .= '"Tax Roll","County","Town","Village","SWIS","Tax ID","Street Number","Street Name","Owner 1","Owner 2","Owner 3","Owner 4",'
.'"Mail Address 1","Mail Address 2","Mail Address 3","Mail City","Mail State","Mail Zip",'
.'"Property Type","East","North","Acres","Full Market Value","Deed Book","Deed Pg",'
.'"County Value","School Value","Town Value","Full Street",'
.'"Solar","STAR","VETS","School",';
foreach ($specialDistType as $type) {
$output .= "\"$type\",";
}
$output .= "\n";
foreach ($formTax as $line) {
$output .= '"'.$town.'",';
foreach ($line as $item) {
$output .= '"'.$item.'",';
}
$output .= "\n";
}
// save output to file
file_put_contents("output-csv/$town.csv", $output);
echo " DONE\n";
}
// last, create a great big file
//system("cat output-csv/*.csv > all-property.csv");
system("zip output-csv.zip output-csv/*");
Real Property Tax Law 1590 requires that municipalities post their tax rolls, within 10 days of the proposed and final rolls being approved. The rolls are generally searchable PDF files, but that isn't that helpful if you are trying to search and compare multiple properties or want to use the North-East Coordinate data to make a map.
This script -- which uses the Linux program pdfttext and other common Linux commands to convert the PDF to a text file, then processes it into a .CSV file that can be opened with a GIS program such as Quantum GIS or a spreadsheet like Microsoft Excel or OpenOffice Calc.
Stuyvesant Plaza is a shopping plaza and office complex located in the McKnownville, near the south end of the Adirondack Northway. First opened in 1959, it focuses on more boutique retailers compared to it's larger cousin, the Crossgates Mall on the other side of the Northway. The plaza is also home to Executive Towers, which is the location of one of the state's large data centers.
Taken on Wednesday August 14, 2019 at Guilderland, New York.Good morning! Yeah, it’s Friday! Two weeks to Labor Day Weekend Begins π¨βπ. Cloudy, humid and 65 degrees at the Elm Ave Park & Ride – CDTA. β There is a south-southeast breeze at 9 mph. π. The dew point is 62 degrees. I’m kind of dripping from the sweat π° walking down to the express bus. The skies will clear Sunday around 7 pm.
I went to bed early last night and got up early today π thinking I would finish packing and then hit up the grocery store and then head to the Adirondacks after work. π Looking at the forecast this morning I changed my mind as Saturday doesn’t look great up north so instead I think I will get up early tomorrow and head north.
That way I’ll only be gone three nights so I expect the ice will last and I won’t have to worry about moving my campsite after three nights. βΊ I don’t expect a lot of people up north tomorrow being it expected to be cloudy and mid August when few people vacation. This way too I can head up on Saturday morning when traffic is light, not have to set up gear in the darkness or buy firewood. Money is a bit tight so everywhere I can save a few bucks it helps.
It will be four days at the potholers through Tuesday cooling off π. Should be nice to lay back on the hammock with a cold one and a book π and be off the grid for a few days. Have nice fires every night π₯, listen to music πΆ as loud as I want, maybe set up targets and shoot guns. π― Basically just get away from it for a few days.
Today will have a chance of showers and thunderstorms, mainly after 1pm. Partly sunny β , with a high of 82 degrees at 3pm. One degree above normal, which is similar to a typical day around August 9th. Maximum dew point of 69 at 3pm. South wind around 9 mph. Chance of precipitation is 30%. New rainfall amounts of less than a tenth of an inch, except higher amounts possible in thunderstorms. A year ago, we had partly cloudy skies in the morning with some clearing in the afternoon. It was sticky. The high last year was 88 degrees. The record high of 97 was set in 1936.
The sun will set at 7:55 pm with dusk around 8:25 pm, which is one minute and 30 seconds earlier than yesterday. π At sunset, look for thunderstorms π© and temperatures around 79 degrees. The dew point will be 68 degrees. There will be a south breeze at 9 mph. Today will have 13 hours and 51 minutes of daytime, an increase of 2 minutes and 35 seconds over yesterday.
Tonight will have a chance of showers and thunderstorms. Mostly cloudy π§, with a low of 68 degrees at 5am. Eight degrees above normal. Maximum dew point of 69 at 6pm. South wind around 9 mph. Chance of precipitation is 40%. New precipitation amounts of less than a tenth of an inch, except higher amounts possible in thunderstorms. In 2018, we had mostly clear skies in the evening, which became light rain by the early hours of the morning. It was very sticky. It got down to 69 degrees. The record low of 40 occurred back in 1979.
Today in 1916, the Migratory Bird Treaty between Canada and the United States signed. π¦ It was designed to save Migratory Birds by giving them international protection for the first time by placing limits on hunting and other means of taking. Gotta buy your duck stamp if your hunting migratory birds.
In 1989, a solar flare from the Sun creates a geomagnetic storm that affects micro chips,β leading to a halt of all trading on Toronto’s stock market. I notice with my display that I built in my bedroom, sometimes in humid weather I have a lot of errors, although in the winter I have less. Not sure if that’s humidity causing shorts and bad connections or if its the lack of shielding on the wires.
Also, in 1993, Debian Linux is announced, it would become the basis of many forms of Linux like Ubuntu Linux, π» which is currently what I run on my home computer.
And in 1966, the House Un-American Activities Committee begins investigations of Americans who have aided the Viet Cong. πΊThe committee intends to introduce legislation making these activities illegal. Anti-war demonstrators disrupt the meeting and 50 people are arrested.
Tomorrow will have a chance of showers, with thunderstorms also possible after noon. Mostly cloudy π¦, with a high of 82 degrees at 3pm. One degree above normal, which is similar to a typical day around August 9th. Maximum dew point of 72 at 1pm. South wind 6 to 8 mph. Chance of precipitation is 40%. New rainfall amounts between a tenth and quarter of an inch, except higher amounts possible in thunderstorms. A year ago, we had partly cloudy skies in the morning with some clearing in the afternoon. It was sticky. The high last year was 86 degrees. The record high of 97 was set in 1913.
Looking ahead to Sunday, a slight chance of showers, then a chance of showers and thunderstorms after 11am. Partly sunny, β with a high near 86. Calm wind becoming south around 5 mph in the afternoon. Chance of precipitation is 40%. New rainfall amounts of less than a tenth of an inch, except higher amounts possible in thunderstorms. Maximum dew point of 70 at 8pm. Typical average high for the weekend is 81 degrees.
The plan is next weekend to stay in town. π‘ But this weekend I’ll head north. I might take the Friday off before Memorial Day Weekend, although it depends if I can get coverage for my clients at work. I also want to take some time off in September and October plus the week before Columbus Day off. Labor Day Weekend I was originally planning on Piseco-Powley Road, but maybe I’ll do what I did last year with that campsite I really like on Jessup River Road or maybe I’ll head back to Vermont. Depends on the forecast.π
As previously noted, there are 2 weeks until Labor Day Weekend Begins π¨βπ when the sun will be setting at 7:32 pm with dusk at 8:01 pm. On that day in 2018, we had humid, partly sunny and temperatures between 82 and 62 degrees. Typically, the high temperature is 78 degrees. We hit a record high of 98 back in 1953.