Записки программиста, обо всем и ни о чем. Но, наверное, больше профессионального.

2012-10-31

Микробы

У Олега Дивова есть много забавных историй. Вот, к примеру, про микро роботов (Симбионты):

Со дня, когда кабинет занял Михаил, косметический ремонт тут делали дважды. Но камеру не заметили, она оставалась на своем месте, и крошечная дырочка рано или поздно снова возникала напротив объектива. Наверное, так было всегда.
Изображение вдруг померкло: что-то лезло в объектив.
Это маленький, едва с булавочную головку, серебристый вертолетик, смешно переваливаясь с боку на бок, вскарабкался по стене и заглянул в дырочку, где пряталась камера…
Вертолетик на стене просунул нос в дырочку, подобрался вплотную к объективу камеры, выдвинул скальпель и поскреб им линзу. Решил, что это неразумно, ухватил объектив манипуляторами и дернул на себя. Замер на секунду, будто призадумался - запросил помощь роя, вдруг решение проблемы уже известно… И повернул объектив против часовой стрелки. Повернул еще.
"Да чтоб тебя! - заорал наблюдатель на другом конце канала. - Да что вам, гады, медом тут намазано?! Ворюги! Третий объектив за месяц!!!"
"Какая хорошая вещь!" - думал вертолетик.
Вывинтил объектив и бодро ускакал с ним вверх по стене.


Какая прелесть.

А родившимся после 1980 рекомендую прочесть «Оружие возмездия». И прикольно и поучительно.

original post http://vasnake.blogspot.com/2012/10/blog-post_31.html

2012-10-30

XMPP bot

До чего же это нудное занятие, прописывать таблицы трансляции. Это я про того бота (GTalk translit.bot@gmail.com). Пять таблиц из одинадцати уже готовы, еще шесть. Можно за неделю управиться.

А тем временем под руку подвернулся целый фреймворк для построения таких ботов на Python. Встречайте

Err - the pluggable chatbot
Err is a plugin based chatbot designed to be easily deployable, extensible and maintainable. It allows you to start scripts interactively from your chatrooms for any reason: random humour, starting a build, monitoring commits, triggering alerts ...
It is open source under the GPL3 license.
It is written and extensible in python and it is based on yapsy with an heavily adapted jabberbot for the XMPP backend.


И к этому чатботу прилагается куча уже готовых плагинов

Может быть, когда нибудь я оформлю мой транслит.бот в виде плагина к Err. Хотя название не вдохновляет (как вы лодку назовете так она и поплывет — (с) Приключения капитана Врунгеля).

original post http://vasnake.blogspot.com/2012/10/xmpp-bot.html

2012-10-29

Великие свершения

Цитата:

... слушал болтовню старика, что рассказывал, повторяя бытовавшие в народе предания о ... , всякие истории об этом строителе-сверхчеловеке, мрачные анекдоты, свидетельства недоброй памяти, на тысячу и больше лет оставшейся у людей ... о грозном царе, добившемся от них невозможного. Говорили, будто он был злым богом и закрыл ради себя все храмы, чтобы никто не похищал у него времени на жертвоприношения. После этого будто бы он взял весь народ в кабалу, обязав всех без исключения строить ему ... и в течение тридцати лет не жалуя никому ни одного часа на собственную жизнь. Десять лет будто бы пришлось им обтесывать и волочить камни, а затем дважды десять лет строить, отдавая этому все свои силы и даже еще немного сверх того. Ибо если бы сложить все их силы, то этих сил оказалось бы недостаточно для такой ... . Необходимый излишек придала им божественность ... , но благодарить тут было не за что. Строительство стоило огромной казны...

Так, по словам старика, говорил народ, и вполне возможно, что через тысячу лет после смерти ... добрую часть рассказов о нем составляли всякие небылицы. Но из этих рассказов, во всяком случае, явствовало, что в народе осталась лишь смешанная со страхом благодарность покойнику за то, что тот, выжав из него все, что в нем было, и еще больше, заставил его совершить невозможное.

Конец цитаты.

Вполне подходит для описания 1920 — 1950 годов в СССР, не правда ли?
А это про фараона Хуфу, из книги «Иосиф и его братья» Томаса нашего Манна.

Занятно.

original post http://vasnake.blogspot.com/2012/10/blog-post_29.html

2012-10-26

Webplatform

Не прошло и 20 лет, как консорциум порешал создать централизованный ресурс по веб-технологиям

Web Platform будет выступать в роли энциклопедии веб-стандартов. Сайт будет содержать постоянно обновляемую информацию о HTML5, CSS и других технологиях.
Основной аудиторией проекта станут веб-разработчики. Зайдя на Web Platform, они смогут узнать о той или иной технологии и ее возможностях, просмотреть примеры ее использования и выяснить, какие браузеры и устройства поддерживают ее, а какие - нет. Это избавит их от необходимости посещать множество сайтов в поисках необходимых данных.



Контента пока не очень много, зато любой может поучаствовать в наполнении

Hot topics



И одна из первых записей в их блоге рассказывает о том, как создавали инфраструктуру для сайта

Our actual statistics for the launch day were:
86,000 visitors
720,000 page views
300 requests per second during the US peak
350 requests per second during the Europe peak.

Our platform currently has the following instances:
5 application servers, with specs:
8GB RAM, 240GB disk, 4 VCPUs
2 database servers, with specs:
16GB RAM, 480GB disk, 4 VCPUs
2 storage servers, with specs:
2GB RAM, 50GB disk (volume storage), 2 VCPUs
1 deployment server, with specs:
2GB RAM, 60GB disk, 2 VCPUs
1 monitoring server, with specs:
2GB RAM, 60GB disk, 2 VCPUs
1 backup server, with specs:
2GB RAM, 50GB disk (volume storage), 2 VCPUs
1 bots server, with specs:
1GB RAM, 30GB disk, 1 VCPU
All instances run Ubuntu Linux (either lucid or precise)


Хороший, годный ресурс.

original post http://vasnake.blogspot.com/2012/10/webplatform.html

2012-10-25

Энергетика

Как по количеству изоляторов на ЛЭП определить напряжение тока?

Сегодня я попытаюсь вкратце рассказать вам о том, как работают энергосистемы высоковольтной энергетики, и для чего предназначены отдельные её элементы, которые мы можем встретить вокруг себя. Сразу скажу - это описание является кратким и упрощённым, некоторые детали опущены или упрощены для лучшего восприятия и понимания, поэтому специалисты в этой области могут заметить некоторые кажущиеся недочёты. Это - не техническое руководство, а популярное описание для тех, кому интересен мир высоковольтной энергетики и ЛЭП.


Занимательно.

original post http://vasnake.blogspot.com/2012/10/blog-post_25.html

2012-10-24

JPype

На фоне современной веб стартапной истерии может показаться, что у языков программирования C/C++, Java и прочих Fortran-ов нет будущего. Что это умирающая культура. Но это не так. Вот, к примеру, Java — масса проектов, невероятное количество полезных (и не очень) библиотек

Just look on Sourceforge, the are 3267 Python-related projects, and 12126 Java-related projects. And that not counting commercial interests

А раз так, очень вероятно, что одна (или много) из существующих Java библиотек может понадобиться при разработке чего-либо на Python. Нет проблем, JPype нас спасет.

JPype is an effort to allow python programs full access to java class libraries. This is achieved not through re-implementing Python, as Jython/JPython has done, but rather through interfacing at the native level in both Virtual Machines.

Once JPype installed (you'll have to hack a bit some files to integrate seamlessly with your system) you can access java classes by doing something like that:
import jpype
jpype.startJVM(jpype.getDefaultJVMPath())
# you can then access to the basic java functions
jpype.java.lang.System.out.println("hello world")
# and you have to shutdown the VM at the end
jpype.shutdownJVM()

Here is a simple example of how to use boilerpipe... from python
import jpype
# start the JVM with the good classpaths
classpath = "dist/boilerpipe-1.1-dev.jar:lib/nekohtml-1.9.13.jar:lib/xerces-2.9.1.jar"
jpype.startJVM(jpype.getDefaultJVMPath(), "-Djava.class.path=%s" % classpath)
# get the Java classes we want to use
DefaultExtractor = jpype.JPackage("de").l3s.boilerpipe.extractors.DefaultExtractor
# call them !
print DefaultExtractor.INSTANCE.getText(jpype.java.net.URL("http://blog.notmyidea.org"))
And you get what you want.

Я не разбирался, каков механизм связи Python с Java VM, а надо бы. Очень интересно. Накладные расходы, побочные эффекты, ограничения и все такое.

original post http://vasnake.blogspot.com/2012/10/jpype.html

2012-10-23

IPython

И чего только люди не придумают, особенно когда эти люди — ученые.


Думаю, что многим хорошо известен продвинутый питоновский шел ipython. Его создатели большие любители пакета Matematika, и при работе в питоне, они скучали по её рабочей среде, которая реализована в виде записной книжки. Там имеется возможность тут же решить уравнение, отобразить результаты решения, нарисовать график, снабдить всё это текстовым комментарием, а при изменении исходных данных всё пересчитать и перерисовать одним нажатием клавиши.

Примерно с год назад разработчики ipython решили, что так жить больше нельзя, и начали изобретать велосипед разрабатывать свою записную книжку. Да так их понесло, что до сих пор не могут остановиться - очень уж им нравится то, что в итоге получается.
...
В научной работе важно протоколировать процесс поиска решения. Нужно знать, что ты уже попробовал, что не сработало и почему. Но в запале, конечно, мало кто это делает систематически.
notebook позволяет делать что-то вроде продвинутого лога всех ваших изысканий. Это инструмент, при помощи которого можно довольно просто и удобно искать решение вашей проблеммы, иллюстрируя всё это тут же создаваемыми графиками, картами или математическими формулами. При желании всё ваши действия можно сохранить, и к любому этапу можно легко вернуться.



Что нам говорит документация:

The goal of IPython is to create a comprehensive environment for interactive and exploratory computing. To support this goal, IPython has two main components:
An enhanced interactive Python shell.
An architecture for interactive parallel computing.



The IPython Notebook consists of two related components:
An JSON based Notebook document format for recording and distributing Python code and rich text.
A web-based user interface for authoring and running notebook documents.

The Notebook can be used by starting the Notebook server with the command:
$ ipython notebook
...
This server uses the same ZeroMQ-based two process kernel architecture as the QT Console as well Tornado for serving HTTP/S requests. Some of the main features of the Notebook include:
Display rich data (png/html/latex/svg) in the browser as a result of computations.
Compose text cells using HTML and Markdown.
Import and export notebook documents in range of formats (.ipynb, .py).
In browser syntax highlighting, tab completion and autoindentation.
Inline matplotlib plots that can be stored in Notebook documents and opened later.


Сразу видно, для экспериментов и исследований вещь хорошая, годная.

original post http://vasnake.blogspot.com/2012/10/ipython.html

XMPP

Намедни я прочел заметку про нашего мальчика xmpp (xmpppy) модуль Python. И так что-то потянуло написать бота какого-нибудь, прям как ребенка на сладкое. Я уж давно не ребенок, во всяком случае внешне, и запретить мне уже никто ничего не может. Поэтому взял и написал.

Знакомься Алиса, это IM бот который занимается транслитерацией - translit.bot@gmail.com. Пока реализовано только три способа транслитерации, но я планирую в свободное время сделать все 10, упомянутые в статье «Транслитерация русского алфавита латиницей». Вместе с http://pypi.python.org/pypi/trans будет одинадцать.

Чтобы попользоваться ботом, добавьте его в свой контакт-лист IM, протокол — GTalk, он же xmpp, он же Jabber. Чтобы прочесть текст «помощи», отправьте ему «help».

Исходники прилагаются (бугага, всего 200 строк вместе таблицами).
Статья:

Про транслит на хабре http://habrahabr.ru/post/137089

original post http://vasnake.blogspot.com/2012/10/xmpp.html

2012-10-19

Tornado

В одну телегу впрячь не можно
Коня и трепетную лань.
Забылся я неосторожно:
Теперь плачу безумствам дань...

Торнадо (Tornado Web Server) предназначен для массовой одновременной обработки тысяч коннектов. Поэтому неудивительно, что он не умеет грамотно отдавать большие статические файлы. Но мы знаем, что если очень хочется, то можно.

Но ситуации могут быть разные. В моём случае через Tornado успешно раздавалось большое количество мелких страничек, хранящихся в SQLite и один большой файл на 200МБ со списком всех доступных URL. Поднимать ради одного этого файла Nginx совершенно не хотелось.
Второй вопрос - "ну так в чем проблема - раздавай на здоровье!". Вот тут мы и сталкиваемся с неприятной особенностью этого сервера - стандартный StaticFileHandler загружает весь файл целиком в память перед тем как отдать его клиенту (пруфлинк). Помимо этого, занятая память не освобождается, если клиент разорвал подключение не скачав весь файл целиком.
Вот эти 2 проблемы и будем решать.


На примере решения вполне практической задачи мы можем многому научиться. Использование Торнадо, генераторы, декораторы и прочее по мелочи. Велкам.


Сцылки
http://www.bibliotekar.ru/encSlov/index.htm

original post http://vasnake.blogspot.com/2012/10/tornado.html

2012-10-18

Очередная практика

Соседняя очередь всегда быстрее

Источники
http://gexxx.livejournal.com/771878.html
http://otecsergiy.livejournal.com/538505.html

Это была практика очередей.
А это теория очередей.


original post http://vasnake.blogspot.com/2012/10/blog-post_18.html

2012-10-17

My own cloud

Поди плохо, иметь свой собственный дропбокс, с блекджеком и шлюхами?

Анонсирован стабильный релиз проекта ownCloud 4.5, в рамках которого развивается система для организации хранения, синхронизации и обмена данными, размещёнными на внешних серверах
...
Сервер ownCloud можно развернуть на любом хостинге, поддерживающем выполнение PHP-скриптов и предоставляющем доступ к SQLite, MySQL или PostgreSQL.
...
выпущен релиз ownCloud Sync Client 1.1.0, клиентского GUI-приложения для синхронизации локальных директорий с хранилищем ownCloud. Варианты клиента подготовлены для Linux, Mac OS X и Windows.


Как я понял, к хост машинам требования самые ненапряжные — PHP и DBMS. Прекрасный проект. Дайте два.


А от еще про облака. Проект Unhosted.

Все вычисления в таком приложении происходят на клиентской стороне, а пользователь сам выбирает место расположения данных, которым может быть специальный публичный сервис, домашняя машина или облачный сервер, взятый в аренду (главное, чтобы на нем был установлен unhosted-сервер). Все, что требуется от пользователя, это просто ввести его идентификатор (GID), состоящий из имени и адреса unhosted-сервера (например, boris@unhosted.org) и пароль. После этого доступ к приложению будет открыт, а вся сгенерированная в процессе информация сохранится в указанном месте в зашифрованном виде.

Unhosted состоит из двух компонентов:
WebDAV-сервер, который принимает запросы на сохранение или доступ к данным от клиентов.
Javascript-библиотека unhosted.js, которую приложение использует для сохранения и чтения данных с сервера.

Обмен данными между клиентом и сервером осуществляется с помощью протокола WebDAV и механизма CORS (Cross-Origin Resource Sharing), разработанного W3C. Аутентификация производится с помощью OAuth. Перед отправкой данные шифруются с использованием алгоритма RSA.


Хранилище отдельно, веб-морда отдельно, логика отдельно. Есть в этом некая футуристичность. Что-то Лем вспомнился с его умной пылью в «Непобедимом».


original post http://vasnake.blogspot.com/2012/10/my-own-cloud.html

2012-10-16

Кино снимать это вам не мешки ворочать

Вот маленькое кино, 12 минут
Но чтобы сделать это кино понадобилась масса усилий:
К работе над фильмом на 7 месяцев были привлечены в режиме полного рабочего дня команда из 12 художников (моделирование, создание анимации, рендеринг, графический дизайн, визуальные эффекты) и разработчиков (доработка Blender и написание скриптов).

Ниче так, семь человекомесяцев на одну минуту кина.

А вообще — правильное решение, делать на Блендере подобные ролики. Уровень доверия к пакету возрастает очень сильно.
http://www.opennet.ru/opennews/art.shtml?num=35001

original post http://vasnake.blogspot.com/2012/10/blog-post_16.html

2012-10-15

Reverse SSH Tunnels

До чего же мощный инструмент, этот SSH. Вот, к примеру, сидите вы дома, за роутером и файрволлом, пробиться снаружи на вашу машину нельзя. А хочется. Что делать? Сделать обратный туннель. Правда, для этого нужен «сервер» к которому можно подключаться по SSH.
С домашней машины устанавливаете соединение с сервером, сервер открывает порт и пробрасывает его обратно на вашу машину. Потом соединившись из любого места с сервером по этому порту вы попадаете на вашу домашнюю машину.

So the steps to create a reverse SSH tunnel are as follows:
From client machine: ssh -R remoteport:localhost:22 username@servername
ex: ssh -R 2048:localhost:22 bob@mylinuxserver.xxx
From server side (to re-establish the tunnel): ssh -p 2048 localhost


А вот, что говорит man ssh на эту тему

-R [bind_address:]port:host:hostport
Specifies that the given port on the remote (server) host is to be forwarded to the given host and port on the local side. This works by allocating a socket to listen to port on the remote side, and whenever a connection is made to this port, the connection is forwarded over the secure channel, and a connection is made to host port hostport from the local machine.

Port forwardings can also be specified in the configuration file. Privileged ports can be forwarded only when logging in as root on the remote machine. IPv6 addresses can be specified by enclosing the address in square braces or using an alternative syntax: [bind_address/]host/port/hostport.

By default, the listening socket on the server will be bound to the loopback interface only. This may be overridden by specifying a bind_address. An empty bind_address, or the address ‘*’, indicates that the remote socket should listen on all interfaces. Specifying a remote bind_address will only succeed if the server's GatewayPorts option is enabled (see sshd_config(5)).

If the port argument is ‘0’, the listen port will be dynamically allocated on the server and reported to the client at run time.

Интересно, в MS Windows по прежнему SSH демон в комплект не входит?

original post http://vasnake.blogspot.com/2012/10/reverse-ssh-tunnels.html

2012-10-12

SQL queries using ArcSDE

Просто поразительно, сколько неприятных открытий может принести создание скрипта на 200 строк, если этот скрипт для ArcGIS. Про предыдущие две неприятности можно почитать тут и тут (даже три). А здесь я напишу про третью четвертую и, надеюсь, последнюю. И вообще, почему вот сразу - «неприятности»? Надо включить позитивный настрой, что нас не убивает то делает нас сильнее.

Как немногим известно, создав соединение с ArcSDE можно через этот коннект запузырить в БД почти любой SQL запрос. В моем случае это сильно облегчает задачу, ибо SDE у меня и так есть а необходимость в модулях типа cx_Oracle отпадает.
Итак, читаю документацию:

The ArcSDESQLExecute object supports the execution of most SQL statements and will return to the user the results of those statements. The object will return a list of lists in the case where the statement returns rows from a table; for statements that do not return rows, it will return an indication of the success or failure of the statement (True for success, None for failure).

Прекрасно, результат вернется в виде None, True или списка. Поскольку у меня запрос на выборку, я буду ждать список. В документации и пример кода есть:
import arcpy
sdeConn = arcpy.ArcSDESQLExecute("data\Connection to GPSERVER3.sde")
sdeReturn = sdeConn.execute(sql)
if isinstance(sdeReturn, list):
    for row in sdeReturn:
        print row
else:
    if sdeReturn == True:
        print "SQL statement: " + sql + " ran sucessfully."
    else:
        print "SQL statement: " + sql + " FAILED."
Да простят меня авторы доки, я выкинул из цитаты несущественное.

Пишу скрипт, тестирую — на выходе все время «FAILED». Ну ёрш твою медь.
Закралось подозрение, что что-то не так с моим запросом. Проверил — все в порядке. Помучался, проверяя разные гипотезы и, наконец, догадался тупо распечатать сразу весь результат. Этот результат (sdeReturn) был прекрасен! В виде строки. Не список, нет. И не булево значение. И не None. Строка в юникоде.
Ну что тут сказать, «не всякому слову верь» - старая добрая истина.

Кто предупрежден, тот вооружен. Правильный код разбора результата теперь такой:
sdeReturn = sdeConn.execute(sql)
log.info("arcpyStuff, ora result '%s', resType '%s'" % (sdeReturn, type(sdeReturn).__name__))
if isinstance(sdeReturn, str) or type(sdeReturn) == unicode:
    log.info("arcpyStuff, ora return string '%s'" % (sdeReturn.strip()))
elif isinstance(sdeReturn, list):
    log.info("arcpyStuff, ora return %s rows" % (len(sdeReturn)))
    for row in sdeReturn:
        log.info("arcpyStuff, row '%s'" % (row))
else:
    if sdeReturn == True: # DDL?
        log.info("arcpyStuff, sql statement ran successfully")
    else:
        log.info("arcpyStuff, error, sql statement FAILED or resType is unknown")
И он останется правильным до следующего открытия, которое может произойти только в результате эксперимента над черным ящиком, именуемым ArcGIS. Закрытые исходники — это безусловное зло.


Оффтоп.
Кому надо звонить по заграницам, обратите внимание на программу Колбаскер (Callbacker)
Она организует соединение абонентов так, что у обоих звонок получается входящий. Выходит очень недорого, главное не пользоваться роумингом а брать местные симки.

original post http://vasnake.blogspot.com/2012/10/sql-queries-using-arcsde.html

2012-10-11

Нету, нету интернету

Сегодня форс-мажор, доступа в Интернет нет ни дома ни на работе. В телефоне есть, но толку с него — чуть. По этому поводу еще одна цитата из «Иосиф и его братья» Томаса Манна

Однако я много ездил между двумя реками, бегущими в разные стороны, одна — с юга на север, а другая наоборот, и знаю, что в мире, который на вид так бесхитростен, существует множество тайн и за внешним шумом скрывается странное и неведомое. Мне часто даже казалось, что мир только потому такой шумный, что за этим шумом удобнее скрыть неведомое, сохранить тайну, стоящую за людьми и вещами. Многое обнаруживалось совершенно неожиданно, и я открывал то, чего не искал.

Читать полностью: http://readr.ru/tomas-mann-iosif-v-egipte.html?page=4#ixzz291DwZuFq

original post http://vasnake.blogspot.com/2012/10/blog-post_11.html

2012-10-10

spatialReference

 - Где я нахожусь?
 - В корзине воздушного шара.


Как и обещал вчера, поговорим о том, куда девается определение системы координат (spatialReference) при передаче FeatureSet в скрипт геопроцессора ArcGIS.
Но сначала закроем вчерашнюю тему, про дырку от бублика. Я нашел только один способ автоматически превращать всякую фигню, нарисованную пользователем, в корректные, с точки зрения ArcGIS, фигуры. Этот способ заключается в использовании Geometry Service «Simplify». И не спрашивайте, почему он так называется - «упростить». Он делает ровно то, что мне нужно — превращает дырки в нормальные полигоны и делает из самопересекающегося полигона правильный составной полигон.
Чтобы использовать этот сервис в прикладухе на ArcGIS Silverlight API, достаточно написать нечто вроде
private void evtDrawComplete(object sender, DrawEventArgs e) {
    currGeom = e.Geometry;
    draw.DrawMode = DrawMode.None;
    draw.IsEnabled = false;
    try {
        var gl = getRLLayer();
        var graphic = new ESRI.ArcGIS.Client.Graphic() {
            Geometry = currGeom, Symbol = polySymbol
        };
        gl.Graphics.Add(graphic);

        var geometryService = new GeometryService("http://tasks.arcgisonline.com/ArcGIS/rest/services/"+
            "Geometry/GeometryServer");
        var graphicList = new List<Graphic>();
        graphicList.Add(graphic);

        geometryService.SimplifyCompleted += (sndr, args) => {
            gl.Graphics.Remove(graphic);
            graphic.Geometry = args.Results[0].Geometry;
            gl.Graphics.Add(graphic);
            askGeoprocessor(graphic.Geometry); // send good polygon to geoprocessor
        };

        geometryService.Failed += (sndr, args) => {
            MessageBox.Show("Сбой нормализации полигона: " + args.Error);
        };

        geometryService.SimplifyAsync(graphicList);
    }
    catch(Exception ex) {
        string msg = string.Format("Сбой отправки запроса: \n [{0}]", ex.Message);
        MessageBox.Show(msg);
    }
}


А теперь таки про spatialReference.
Фишка в том, что в Python скрипте геопроцессора нет доступа к сведениям о системе координат переданного в скрипт полигона (используется FeatureSet), хотя сведения эти передаются явным образом
inputPolygon={
"geometryType":"esriGeometryPolygon",
"spatialReference":{"wkid":102100},
"features":[{
 "geometry":{
  "spatialReference":{"wkid":102100},
  "rings":[[[7592337.47835702,9803507.48815798],[7924991.42545401,10312272.348424],[8277213.25179201,9979618.40132698],[7592337.47835702,9803507.48815798]]]
 },
 "attributes":{}
}]}
Проведенные тесты показывают, что где-то глубоко внутре используемых обьектов эта информация есть, равно как и координаты дырки от бублика. Просто через API не выходит получить прямой доступ к данным.

Но важно не это, важно другое — что же делать, трахтибидох? Какой смысл в координатах если мы не знаем систему координат, точку отсчета?

На мой взгляд, сделать можно две вещи: передавать spatialreference отдельным параметром и/или трансформировать переданные координаты в известную и желаемую систему координат. Второй способ лично мне нравится больше.
Вот смотрите
import arcpy
from arcpy import env

fsetObj = arcpy.GetParameter(0)
fsetDesc = arcpy.Describe(fsetObj)
if hasattr(fsetDesc, 'spatialReference'): log.info("arcpyStuff, input fset spatialReference '%s'" % fsetDesc.spatialReference) # haven't

WKID = 4326 # WGS-1984 http://anothergisblog.blogspot.com/2011/05/spatial-reference-class.html
sr = arcpy.SpatialReference()
sr.factoryCode = WKID
sr.create()
# env.outputCoordinateSystem = sr

# или возьмем spatialreference из заранее подготовленного featureclass
gdbPath = r'''\\cache\MXD\seismo\Seis_button.gdb'''
seisFCName = r'''APP_GP_SEISM2D_L'''
seisDesc = arcpy.Describe(os.path.join(gdbPath, seisFCName))
log.info("arcpyStuff, seismoprofiles WKID '%s'" % (seisDesc.spatialReference.factoryCode))

rows = arcpy.SearchCursor(fsetObj, '', sr) # decimal degree
# rows = arcpy.SearchCursor(fsetObj, '', seisDesc.spatialReference) # meters
for row in rows:
    geom = row.shape
    log.info("arcpyStuff searchcursor, geometry geojson '%s'" % (geom.__geo_interface__)) # {'type': 'Polygon', 'coordinates': []}
    if hasattr(geom, 'spatialReference'): log.info("arcpyStuff searchcursor, geometry spatialReference '%s'" % (geom.spatialReference)) # haven't
    if geom.partCount <= 0 or geom.area <=0:
        raise NameError("Wrong input polygon, you should send no selfintersected clockwise drawed single ring")
    for part in geom:
        log.info("arcpyStuff searchcursor, geometry part, len '%s'" % (len(part)))
        for pnt in part:
            log.info("arcpyStuff searchcursor, point x '%s', y '%s'" % (pnt.X, pnt.Y))
Трансформация происходит (задается) на строке
rows = arcpy.SearchCursor(fsetObj, '', sr) # decimal degree
И, как ни странно, это работает. На входе имеем
WKID = 102100
geometry geojson '{'type': 'Polygon', 'coordinates': [[(7924991.4255000018, 10390543.865400001), (8257645.3726000004, 9803507.4882000014), (7631473.2368000001, 9901346.8844000027), (7924991.4255000018, 10390543.865400001)]]}'
а на выходе
WKID = 4326
geometry geojson '{'type': 'Polygon', 'coordinates': [[(71.191409240428044, 67.809244466732096), (74.17969049045422, 65.730626450487776), (68.554690489665163, 66.089364228422752), (71.191409240428044, 67.809244466732096)]]}'
Легко проверить, что это одни и те же координаты, только в разных СК.

original post http://vasnake.blogspot.com/2012/10/spatialreference.html

2012-10-09

Колбасой вниз

Неправильно ты, дядя Федор, бутерброд ешь

Продолжая вчерашнюю тему, про скрипт геопроцессинга в ArcGIS.
Один из параметров, передаваемых в скрипт, должен быть полигоном. Казалось бы, чего там, замкнутая последовательность координат. Для проверки, чего там в скрипт пришло, пишу примитивную распечатку
import arcpy
fsetObj = arcpy.GetParameter(0)
log.info("arcpyStuff, input polygons obj '%s'" % (fsetObj)) # geoprocessing record set object (FeatureSet)
rows = arcpy.SearchCursor(fsetObj)
for row in rows:
    geom = row.shape
    log.info("arcpyStuff searchcursor, geometry type '%s', area '%s', parts '%s'" % (geom.type, geom.area, geom.partCount))
    log.info("arcpyStuff searchcursor, geometry geojson '%s'" % (geom.__geo_interface__))
    for part in geom:
        for pnt in part:
            log.info("arcpyStuff searchcursor, point x '%s', y '%s'" % (pnt.X, pnt.Y))

Тестирую. В одном случае получаю вполне приличный выхлоп
arcpyStuff, input polygons obj '<geoprocessing record set object object at 0x0B88D320>'
arcpyStuff searchcursor, geometry type 'polygon', area '162541855691.0', parts '1'
arcpyStuff searchcursor, geometry geojson '{'type': 'Polygon', 'coordinates': [[(7631473.2368000001, 9783939.6089000031), (7807584.1499999985, 10370975.986100003), (8238077.4932999983, 9960050.5221000016), (7631473.2368000001, 9783939.6089000031)]]}'
arcpyStuff searchcursor, point x '7631473.2368', y '9783939.6089'
arcpyStuff searchcursor, point x '7807584.15', y '10370975.9861'
arcpyStuff searchcursor, point x '8238077.4933', y '9960050.5221'
arcpyStuff searchcursor, point x '7631473.2368', y '9783939.6089'

А в другом случае фигня какая-то
arcpyStuff, input polygons obj '<geoprocessing record set object object at 0x0B88D1A0>'
arcpyStuff searchcursor, geometry type 'polygon', area '-124443116821.0', parts '0'
arcpyStuff searchcursor, geometry geojson '{'type': 'Polygon', 'coordinates': []}'
При этом на вход я засылаю практически идентичные треугольники. Как такое может быть, чтобы у полигона не было координат и при этом была отрицательная площадь?
Да очень просто. Фишка называется «внутреннее кольцо» (interior ring) или дырка от бублика. Достаточно при отрисовке полигона рисовать его против часовой стрелки, чтобы ArcGIS воспринял его как дырку от бублика.

Беда в том, что ситуация «дырка от бублика» имеет смысл если полигон состоит из минимум двух колец (ring) — внешнего и внутреннего. А если кольцо только одно, как в моем случае (треугольник нарисован против часовой стрелки), то про дырки можно забыть, нету их по определению. Но ArcGIS не может похвастаться интеллектом. Нарисовал против часовой стрелки — значит дырка и ниипет.
А отягощается это логикой разделения колец в полигоне. Координаты дырки отделяются от внешнего кольца нуллом (null). Что будет если внешнего кольца нет? Один нулл и ничего больше. Как результат — я не могу получить присланные координаты. Фак. Зато площадь отрицательную могу получить.

Так и живем — отправить координаты можно а получить их нельзя. При этом ни один валидатор ArcGIS и не думает ругацца. А что? Дырка от бублика это нормально. И это не единственная проблема, см.сцылки в хвосте. Про то, куда девается определение системы координат (spatial reference) поговорим в другой раз.

Остается только одно, ужесточить требования к входным параметрам и требовать на вход уже валидный полигон, обьясняя это тем, что добрые люди не позволяют выполнить валидацию и исправление геометрии на сервере. Пусть пользователь рисует аккуратно, по часовой стрелке.


Приложение

Правильный полигон
inputPolygon={
"geometryType":"esriGeometryPolygon",
"spatialReference":{"wkid":102100},
"features":[{
 "geometry":{
  "spatialReference":{"wkid":102100},
  "rings":[[[7592337.47835702,9803507.48815798],[7924991.42545401,10312272.348424],[8277213.25179201,9979618.40132698],[7592337.47835702,9803507.48815798]]]
 },
 "attributes":{}
}]}
Неправильный полигон — дырка от бублика
inputPolygon={
"geometryType" : "esriGeometryPolygon",
"spatialReference" : {"wkid" : 4326},
"fields": [ {
 "name": "Name",
 "type": "esriFieldTypeString",
 "alias": "Name"
} ],
"features"  : [{
 "geometry" : {
  "rings" : [[ [-97.06326,32.759], [-97.06298,32.755], [-97.06153,32.749], [-97.06326,32.759] ]],
  "spatialReference" : {"wkid" : 4326}
 },
 "attributes" : {"Name" : "Feature 1"}
}]}

Сцылки

2012-10-08

Выйти из окружения

Surrounding wednesday

Сижу, работаю — пишу скрипт на Python, с целью сделать из этого скрипта службу геопроцессинга для сервера ArcGIS. Поскольку скрипт работает в качестве службы, то с отладкой не все просто. Применяю свой излюбленный прием, вывод всего подряд в журнал — лог-файл, благо в Python есть развесистая библиотека для этого.
В какой-то момент включаю в настройках скрипта галочку «in process», и понеслась — записи в журнале начали дублироваться, с каждым новым запросом службы добавляется по дублю. Что характерно, если убрать галочку «ин процесс», то никаких дублей не наблюдается.
Какие могут быть гипотезы? Да любые. А правильная — хост не выгружает модуль скрипта из памяти по завершению, поэтому при каждом новом запуске, в застрявший в памяти обьект журнала добавляется новый хандлер файла для записи. Если более общо — глобальные переменные не зачищаются по завершении работы модуля. Даже logging.shutdown() не помогает.

В итоге разборок родился грязный хак (по уму надо бы завернуть всю логику в класс с конструктором и деструктором) для ловли повторной инициализации глобального обьекта.
За вычетом несущественных для данной темы деталей, скрипт вышел такой
import logging
logFilename = '//cache/MXD/seismo/seismodensity.geoproc.log'
log = logging.getLogger('seismodens') # http://docs.python.org/library/logging.html

def setLogger(log):
    log.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    if not hasattr(log, 'vFHandle'):
        fh = logging.FileHandler(logFilename)
        fh.setLevel(logging.DEBUG)
        fh.setFormatter(formatter)
        log.addHandler(fh)
        log.vFHandle = fh
    print 'Log configured. Look file [%s] for messages' % logFilename

def main(note=''):
    setLogger(log)
    log.info('start, argv: %s, note "%s"' % (argv, note))
    import arcpy
    try:
        arcpyStuff()
    except Exception, e:
        arcpy.AddError(e)
        if type(e).__name__ == 'COMError':
            log.error('main, COM error, msg [%s]' % e)
        else:
            log.exception('main program failed')
            raise
    finally:
        log.info('logging shutdown')
        logging.shutdown()

if __name__ == "__main__":
    try:
        main()
    except Exception, e:
        if type(e).__name__ == 'COMError': print 'COM error, msg [%s]' % e
        else:
            print 'Error, program failed:'
            traceback.print_exc(file=sys.stderr)
Вся фишка тут
    if not hasattr(log, 'vFHandle'):
Теперь журнал выглядит как положено.

original post http://vasnake.blogspot.com/2012/10/blog-post_8.html

2012-10-05

Доверие и требовательность

Вот такая загогулина.

Уже несколько дней размышляю над тем, чтобы реорганизовать свою схему хранения проектов и рабочих материалов. Что-то сложно стало находить нужную информацию.
За годы работы накопилось уже немало всяческих проектов, и большая часть из них содержит внутре всякие know-how по разным областям IT. И вот, сижу я такой задумчивый, вспоминаю, в каком году и в каком проекте я решал задачу, скажем, вызова в Python хранимой процедуры из БД Оракл, с передачей параметра через переменную. Ну, типа, чтобы не тратить время на воспроизведение, а по быстрому скопипастить сниппет кода.
И в силу большого количества файлов, прошедшего времени и деградации памяти :) трачу больше времени на поиск сниппета чем на его написание с нуля.

Неправильно это.

Вот я и задумался над реорганизацией хранения материалов. Думаю, может разложить все по папочкам с названиями ключевых технологий? Тогда любое интегрированное решение распадается на несвязанные куски, хрен соберешь. Или заняться ведением Каталога? Замучаешься его синхронизировать — любое перемещение папки с материалами нужно адекватно отразить в Каталоге. Или завести хранилище сниппетов, куда копипастить из проектов полезные куски? А как заранее узнать, что будет полезно а что нет?

Как нам трудно живется :) (цитата из «Одна за всех»).


Еще немного из Томаса нашего Манна

Скажи мне, какая вина довела твою жизнь до ямы.
Она заслуживала наказания и называлась доверие. Преступное доверие и слепая требовательность — вот ее имя. Ибо тот слеп и достоин смерти, у кого к людям больше доверия, чем они в силах вынести, и кто предъявляет к ним слишком большие требования, при виде такой любви и такого уважения к ним они выходят из себя и делаются похожи на хищных зверей. Пагубно не знать этого или не хотеть знать.


original post http://vasnake.blogspot.com/2012/10/blog-post_5.html

2012-10-04

Ликбез

Какая патриотическая прелесть

Когда одурманенный западной пропагандой программист покупается на предложение о работе и уезжает — он перестает быть нашим соотечественником. Не приносит той пользы нашему обществу, какую мог бы принести.
То есть логически такое «сваливание» очень напоминает разновидность коррупции.
Поэтому таких людей в нашем обществе уважают только такие же как они.
Так вот, к вопросу что ты лично сделал для своей страны?
Хочу взять на свои плечи одну посильную ношу. Как известно, первый свой сайт я сделал в далеком 1999 году (закончив курсы веб-разработки в том же ИТМО).
За вот уже почти 14 лет веб-разработки мне многое есть что рассказать и чему научить вас, уважаемые читатели.
Поэтому я объявляю об открытии нового блога, где уже ведется обучение веб-разработчиков.


Но не смотря на признаки ПГМ, автор может быть полезен. Его проект
вполне годится в качестве вводного курса в дело веб-разработки. Написано очень доступным языком.
Пример

Сегодня мы поговорим о веб-сервере. Это программа, которая в буквальном смысле «раздает» сайты с сервера по запросу клиентов, то есть нас с вами. Часто веб-сервер путают с просто «сервером», поэтому я искренне надеюсь, что после прочтения этого материала вы никогда не сможете подловить себя на этой неточности.


Нубам — обязательно к освоению, ящетаю.

original post http://vasnake.blogspot.com/2012/10/blog-post_4.html

2012-10-03

Лучше знать, чем нет

Ученье — свет, а неученых — тьма.

Не все так плохо в этих ваших Штатах

Знаете, у специалистов по компьютерной безопасности есть такой термин: "security through obscurity". Оно означает попытку обеспечить безопасность системы или софта с помощью преднамеренного сокрытия информации о всех багах/дырах ... чаще всего, применяют принцип обратный. То есть, "предупреждён - значит, вооружён". И потому среди материалов курса по безопасному вождению (!) можно запросто найти таблички с полным описанием, как выглядят те или иные наркотические препараты (!!), какие у них сленговые названия, как их следует принимать, и как они действуют.

http://cybernatic-cat.livejournal.com/1271800.html (там и картинки есть)

Гыы, «как их следует принимать»! Наверное таки «как их обычно принимают». А в целом да, уж лучше знать о вражине побольше, чем не знать о нем. Эвон, кто может, даже спецслужбы выращивает с целью узнавания всякого о всяком.

Что-то я в открытом доступе не нашел упомянутого сайберкотом ресурса. Зато нашел другой, не менее толковый


Просвещайтесь.

original post http://vasnake.blogspot.com/2012/10/blog-post_3.html

2012-10-02

Религиозность

Было дело, залил я когда-то в смартфон книжки, для почитать. Чтобы выпендриться выбрал не Акунина или Донцову а вовсе даже наоборот, Томаса Манна, про Иосифа и братьев. И когда очередь подошла — стал читать. Открываю первый том, не открывается. Второй — нет. И так до четвертого, он уже открылся в читалке нормально, хз почему. Ну ладно, не все ли равно, даже интереснее бывает с конца читать, понятнее, что автор донести хотел. Прочел четвертый том и стал читать послесловие, о чем вообще вся книга. А там про религиозность. У нас это нынче модно, вот, не поленитесь и не пожалейте времени, проникнитесь.
Цитирую:

я сказал бы: религиозность — это внимание и послушание ; внимание к внутренним изменениям, которые претерпевает мир, к изменчивой картине представлений об истине и справедливости; послушание, которое немедля приспосабливает жизнь и действительность к этим изменениям, к этим новым представлениям и следует таким образом велениям разума. Жить во грехе — значит жить не так, как этого хочет разум, по невнимательности и из непослушания цепляться за устаревшее и отсталое и продолжать жить в этом заблуждении. И каждый раз, когда в книге заходит речь насчет «заботы о боге», речь идет о праведном страхе перед этим грехом и безрассудством. Эта «забота о боге» живет в моем романе повсюду: на пастбищах Ханаанских и на престоле Египетского царства. «Думать о боге» — значит не только стараться «выдумать» его, определить, что он такое, познать его, это прежде всего значит думать о том, чтобы выполнить его волю, с которой должны гармонировать наши помыслы, не упустить сделать то, чему пришла пора свершиться, чему уже пробил срок на часах истории, чего требует век. Кто «заботится о боге», тот озабочен мыслью: не продолжает ли он считать правильным и справедливым то, что некогда действительно было истиной, но перестало быть ею, не живет ли он по этим, ставшим анахронизмом канонам; «забота о боге» — это благочестивое смирение, уменье распознать дурное, устаревшее, все то, из чего человек уже внутренне вырос, что стало нестерпимым, невыносимым, или, на языке Израиля, «скверной». «Заботиться о боге» — значит всеми силами своей души внимать велениям мирового разума, прислушиваться к новой истине и необходимости, и отсюда вытекает особое, религиозное понятие о глупости : глупости перед богом, которая не ведает этой заботы или же пытается отдать ей дань, но делает это так неуклюже, как родители Потифара, ставшие супругами брат и сестра, приносящие в жертву Свету детородную способность своего сына. Глупцом перед богом оказывается и Лаван, все еще верящий в то, что долг повелевает ему заколоть своего маленького сына и похоронить его под фундаментом дома, что некогда считалось делом весьма благочестивым, но теперь уже не считается признаком благочестия. Первоначально люди знали только один вид жертвоприношения — приношение в жертву человека. Когда же наступил момент, в который человеческие жертвы стали считаться «скверной» и глупостью? Книга Бытия фиксирует этот момент в рассказе об Аврааме, который отказался заклать сына своего Исаака, заменив человеческую жертву животным. Здесь мы видим человека, уже настолько далеко ушедшего в познании бога, что он расстается с отжившим обычаем, выполняя волю божества, которое стремится приподнять — и уже приподняло нас — над подобными предрассудками. Благочестие — это своего рода мудрость: мудрость перед богом.

Нужно ли добавлять, что страдания, бремя которых мы сейчас несем, катастрофу, которая на нас обрушилась, мы навлекли на себя тем, что в нашем легкомыслии, которое давно уже стало преступным, растеряли последние остатки этой мудрости перед богом?

Конец цитаты.

Томас Манн, Иосиф-кормилец (Иосиф и его братья, книга 4)

Написано до, во время и после Второй Мировой Войны.
Очень точно, доходчиво и исчерпывающе. И безо всякой псевдонаучной марксистской мутотени про производственные отношения и производительные силы. Но о том же, фактически.
Это вам не патриарх Кирилл жук начхал.

original post http://vasnake.blogspot.com/2012/10/blog-post_2.html

2012-10-01

Есть что почитать

Наступило 1 октября. Это я осознал, читая утречком смс-ку из банка о снятии с моей кредитки 12 долларов за книжку из Амазона. Сначала пришла смс-ка а потом в читалке на айпадке и книжка появилась. Почитаю теперь :)

А еще можно почитать из свеженайденного блога
про ГИС, Сильверлайт, Microsoft SQL Server, пространственные данные. Там этого достаточно.
И вот еще
про Microsoft SQL Server Spatial из первых рук.

original post http://vasnake.blogspot.com/2012/10/blog-post.html

Архив блога

Ярлыки

linux (241) python (191) citation (186) web-develop (170) gov.ru (159) video (124) бытовуха (115) sysadm (100) GIS (97) Zope(Plone) (88) бурчалки (84) Book (83) programming (82) грабли (77) Fun (76) development (73) windsurfing (72) Microsoft (64) hiload (62) internet provider (57) opensource (57) security (57) опыт (55) movie (52) Wisdom (51) ML (47) driving (45) hardware (45) language (45) money (42) JS (41) curse (40) bigdata (39) DBMS (38) ArcGIS (34) history (31) PDA (30) howto (30) holyday (29) Google (27) Oracle (27) tourism (27) virtbox (27) health (26) vacation (24) AI (23) Autodesk (23) SQL (23) Java (22) humor (22) knowledge (22) translate (20) CSS (19) cheatsheet (19) hack (19) Apache (16) Manager (15) web-browser (15) Никонов (15) functional programming (14) happiness (14) music (14) todo (14) PHP (13) course (13) scala (13) weapon (13) HTTP. Apache (12) Klaipeda (12) SSH (12) frameworks (12) hero (12) im (12) settings (12) HTML (11) SciTE (11) USA (11) crypto (11) game (11) map (11) HTTPD (9) ODF (9) купи/продай (9) Photo (8) benchmark (8) documentation (8) 3D (7) CS (7) DNS (7) NoSQL (7) cloud (7) django (7) gun (7) matroska (7) telephony (7) Microsoft Office (6) VCS (6) bluetooth (6) pidgin (6) proxy (6) Donald Knuth (5) ETL (5) NVIDIA (5) Palanga (5) REST (5) bash (5) flash (5) keyboard (5) price (5) samba (5) CGI (4) LISP (4) RoR (4) cache (4) car (4) display (4) holywar (4) nginx (4) pistol (4) spark (4) xml (4) Лебедев (4) IDE (3) IE8 (3) J2EE (3) NTFS (3) RDP (3) holiday (3) mount (3) Гоблин (3) кухня (3) урюк (3) AMQP (2) ERP (2) IE7 (2) NAS (2) Naudoc (2) PDF (2) address (2) air (2) british (2) coffee (2) fitness (2) font (2) ftp (2) fuckup (2) messaging (2) notify (2) sharepoint (2) ssl/tls (2) stardict (2) tests (2) tunnel (2) udev (2) APT (1) CRUD (1) Canyonlands (1) Cyprus (1) DVDShrink (1) Jabber (1) K9Copy (1) Matlab (1) Portugal (1) VBA (1) WD My Book (1) autoit (1) bike (1) cannabis (1) chat (1) concurrent (1) dbf (1) ext4 (1) idioten (1) join (1) krusader (1) license (1) life (1) migration (1) mindmap (1) navitel (1) pneumatic weapon (1) quiz (1) regexp (1) robot (1) science (1) serialization (1) spatial (1) tie (1) vim (1) Науру (1) крысы (1) налоги (1) пианино (1)