Skip to content

Commit

Permalink
#115 Fixing range queries for bc dates
Browse files Browse the repository at this point in the history
  • Loading branch information
carolinux committed May 20, 2015
1 parent 510b122 commit e6d6a22
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 23 deletions.
34 changes: 24 additions & 10 deletions query_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,24 +60,38 @@ def greaterThan(val, col, equals=False):
comparison = '>' if not equals else '>='
return " '{}' {} \"{}\" ".format(val,comparison,col)

def isAfter(col,val, equals=False, bc=False):
if not bc:
return lessThan(val,col,equals)
else:
return greaterThan(val,col,equals)

def isBefore(col,val, equals=False, bc=False):
return isAfter(col,val,equals, not bc)

def paren(q):
return "( "+q+" )"

def build_query_archaelogical(start_str, end_str, from_attr, to_attr, comparison, query_idiom):
# start_attr <- from_attr, end_attr <- to_attr
def build_query_archaelogical(start_str, end_str, start_attr, end_attr, comparison, query_idiom):
if "BC" in start_str and "BC" in end_str:
# for BC need to invert the order of comparisons
return likeBC(from_attr) + AND + likeBC(to_attr) + AND + greaterThan(val = start_str, col = to_attr, equals = True) + AND\
+ lessThan(val = end_str, col=from_attr, equals=('=' in comparison))
return paren(paren(likeBC(end_attr)+AND+isAfter( col=end_attr, val=start_str, equals =True, bc=True))+OR+likeAD(end_attr))\
+ AND\
+ paren(likeBC(start_attr)+AND+isBefore(col=start_attr, val = end_str, equals=('=' in comparison), bc= True))

if "AD" in start_str and "AD" in end_str:
return likeAD(from_attr) + AND + likeAD(to_attr) + AND + lessThan(val = start_str, col = to_attr, equals = True) + AND\
+ greaterThan(val = end_str, col=from_attr, equals=('=' in comparison))
# can only be from_attr = BC and to_attr = AD
return paren(NOT(likeAD(from_attr)) + OR + paren(likeAD(from_attr) + AND\
+ greaterThan(val = end_str, col=from_attr, equals=('=' in comparison))))\
return paren(likeAD(end_attr)+AND+isAfter( col=end_attr, val=start_str, equals =True, bc=False))\
+ AND\
+ paren(likeBC(start_attr)+OR+paren(isBefore(col=start_attr, val = end_str, equals=('=' in comparison), bc=False)\
+AND+likeAD(start_attr)))

# can only be start_attr = BC and end_attr = AD
return paren(NOT(likeAD(start_attr)) + OR + paren(likeAD(start_attr) + AND\
+ greaterThan(val = end_str, col=start_attr, equals=('=' in comparison))))\
+ AND\
+ paren(NOT(likeBC(to_attr)) + OR + paren(likeBC(to_attr) + AND\
+ greaterThan(val = start_str, col = to_attr, equals=True)))
+ paren(NOT(likeBC(end_attr)) + OR + paren(likeBC(end_attr) + AND\
+ greaterThan(val = start_str, col = end_attr, equals=True)))


def build_query(start_dt, end_dt, from_attr, to_attr, date_type, date_format, query_idiom):
Expand Down
58 changes: 46 additions & 12 deletions test/test_functionality.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
# export QT_API=pyqt
from qgis.core import *
from qgis.gui import *
import sys
sys.path.insert(0,'../..')
import os
from mock import Mock
from datetime import datetime, timedelta
Expand All @@ -15,9 +17,11 @@
from TimeManager.timelayermanager import TimeLayerManager
import testcfg
import TimeManager.time_util as time_util
import TimeManager.bcdate_util as bcdate_util
import TimeManager.os_util as os_util
import TimeManager.layer_settings as ls


from abc import ABCMeta, abstractmethod
import tempfile
import shutil
Expand Down Expand Up @@ -72,15 +76,14 @@ class TestWithQGISLauncher(unittest.TestCase):

@classmethod
def setUpClass(cls):

os.environ["QGIS_DEBUG"] = str(-1)

QtCore.QCoreApplication.setOrganizationName('QGIS')
QtCore.QCoreApplication.setApplicationName('QGIS2')

prefix = os_util.get_possible_prefix_path() if PREFIX_PATH is None else PREFIX_PATH
QgsApplication.setPrefixPath(prefix, True)

print "init qgis"
QgsApplication.initQgis()

if len(QgsProviderRegistry.instance().providerList()) == 0:
Expand Down Expand Up @@ -311,15 +314,46 @@ def test_with_two_layers(self):
self.tlm.removeTimeLayer(self.tlm.getTimeLayerList()[0].getLayerId())
self.assertAlmostEqual(self.tlm.getProjectTimeExtents(), (None,None))


# Ideas for more tests:
# Test save string, settings, restoring, disabling timemanager
#TODO (low prio): Test what happens with impossible events ie:
#test what happens when trying to setCurrentTimePosition to sth wrong
#test layers with nulls


if __name__=="__main__":
unittest.main()
def getArchaelogicalLayer(self):
testfile_dir = testcfg.TEST_DATA_DIR
fn = os.path.join(testfile_dir,"archaelogical2.txt")
uri = "{}?type=csv&xField={}&yField={}&spatialIndex=no&subsetIndex=no&watchFile=no" \
"".format(fn, "lon", "lat")
layer = QgsVectorLayer(uri, "ancient_points", 'delimitedtext')
return layer

def test_archaeological_range_queries(self):
try:
layer = self.getArchaelogicalLayer()
self.ctrl.setArchaeology(1)
assert(time_util.is_archaelogical())
settings = ls.LayerSettings()
settings.layer = layer
settings.startTimeAttribute = "year"
settings.endTimeAttribute = "endyear"
iface=Mock()
timeLayer = timevectorlayer.TimeVectorLayer(settings, iface)
self.tlm.registerTimeLayer(timeLayer)
self.assertEquals(len(self.tlm.getActiveVectors()),1)
self.assertEquals(timeLayer.getDateType(), time_util.DateTypes.DatesAsStringsArchaelogical)
self.assertEquals(timeLayer.getTimeFormat(), bcdate_util.BC_FORMAT)
self.tlm.setTimeFrameType("years")
self.tlm.setCurrentTimePosition(bcdate_util.BCDate(-352))
self.assertEquals(layer.featureCount(),2)
self.tlm.setCurrentTimePosition(bcdate_util.BCDate(180))
self.assertEquals(layer.featureCount(),0)
self.tlm.setCurrentTimePosition(bcdate_util.BCDate(1))
self.assertEquals(layer.featureCount(),2)
self.tlm.setCurrentTimePosition(bcdate_util.BCDate(333))
self.assertEquals(layer.featureCount(),1)
#expected_datetime = time_util.epoch_to_datetime(self.get_start_time())
#self.assertEquals(self.tlm.getCurrentTimePosition(),expected_datetime)
#self.assertEquals(layer.featureCount(),1)
#self.tlm.stepForward()
#self.tlm.setTimeFrameSize(2)
self.ctrl.setArchaeology(0)
except Exception, e:
self.ctrl.setArchaeology(0)
raise e


6 changes: 6 additions & 0 deletions testdata/archaelogical2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
id,year,endyear,lon,lat
1,0352 BC,0300 BC,1,1
2,0400 BC,0001 AD,1.1,1.1
3,0200 BC,0190 BC,1.2,1
4,0200 AD,1000 AD,1,1.2
5,0010 BC,0002 AD,1.1,1.3
5 changes: 4 additions & 1 deletion timemanagercontrol.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,10 @@ def setArchaeology(self, enabled):
self.guiControl.setWindowTitle("Time Manager Archaeology Mode")
self.guiControl.setArchaeologyPressed(True)
ctx = self.guiControl.dock.objectName()
self.guiControl.setTimeFrameType(QCoreApplication.translate(ctx,'years'))
try:
self.guiControl.setTimeFrameType(QCoreApplication.translate(ctx,'years'))
except:
error("should only happen during testing")
self.guiControl.enableArchaeologyTextBox()
self.showMessage("Archaelogy mode enabled. Expecting data of the form YYYY BC or YYYY AD."+\
" Disable to work with regular datetimes from year 1 onwards")
Expand Down

0 comments on commit e6d6a22

Please sign in to comment.