Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shakeb #11

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
.project
.pydevproject

py_bind/optv/*.c

*.pyc

liboptv/config.h.in~
Expand Down
26 changes: 26 additions & 0 deletions liboptv/include/parameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,33 @@ typedef struct {
mm_np *mm;
} control_par;

typedef struct {
int seq_first;
int seq_last;
int max_shaking_points;
int max_shaking_frames;
} shaking_par;

/* compare_shaking_par(shaking_par *, shaking_par * ) checks deep equality between two shaking_par structs.
Arguments: shaking_par * s1, shaking_par * s2 - pointers to the structs for comparison.

Returns:
True (1) if equal, false (0) otherwise.
*/
int compare_shaking_par(shaking_par * s1, shaking_par * s2);

/* read_shaking_par() reads 4 shaking parameters from a text file line by line
Arguments:
char *filename - path to the text file containing the parameters.
Returns:
Pointer to a newly-allocated shaking_par structure. Don't forget to free
the new memory that is allocated for the image names.
Returns NULL in case of any reading error.
*/
shaking_par * read_shaking_par(char* filename);

control_par * read_control_par(char *filename);

void free_control_par(control_par *cp);

/* Checks deep equality between two mm_np struct instances.
Expand Down
54 changes: 54 additions & 0 deletions liboptv/src/parameters.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,3 +337,57 @@ int compare_mm_np(mm_np *mm_np1, mm_np *mm_np2)
return 0;
return 1;
}

/* read_shaking_par() reads 4 shaking parameters from a text file line by line

Arguments:
char *filename - path to the text file containing the parameters.

Returns:
Pointer to a newly-allocated shaking_par structure. Don't forget to free
the new memory that is allocated for the image names.
Returns NULL in case of any reading error.
*/
shaking_par * read_shaking_par(char* filename) {
FILE *par_file;
shaking_par *ret; //returned pointer to shaking_par struct

par_file = fopen(filename, "r");
if (par_file == NULL) {
printf("Failed to open %s\n", filename);
return NULL;
}

ret = (shaking_par *) malloc(sizeof(shaking_par));

if (fscanf(par_file, "%d\n", &(ret->seq_first)) == 0
|| fscanf(par_file, "%d\n", &(ret->seq_last)) == 0
|| fscanf(par_file, "%d\n", &(ret->max_shaking_points)) == 0
|| fscanf(par_file, "%d\n", &(ret->max_shaking_frames)) == 0)
{
printf("Error reading shaking parameters from %s\n", filename);
free(ret);
fclose(par_file);
return NULL;
}

fclose(par_file);
return ret;

}

/* compare_shaking_par(shaking_par *, shaking_par * ) checks deep equality between two shaking_par structs.
Arguments: shaking_par * s1, shaking_par * s2 - pointers to the structs for comparison.

Returns:
True (1) if equal, false (0) otherwise.
*/
int compare_shaking_par(shaking_par * s1, shaking_par * s2) {
if ( s1->seq_first != s2->seq_first
|| s1->seq_last != s2->seq_last
|| s1->max_shaking_points != s2->max_shaking_points
|| s1->max_shaking_frames != s2->max_shaking_frames )
return 0;
return 1;
}

21 changes: 20 additions & 1 deletion liboptv/tests/check_parameters.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@
#include <stdio.h>
#include "parameters.h"

START_TEST( test_read_shaking_par)
{
shaking_par * sp_test; //TODO change back to 100!
shaking_par sp_correct = { 410000, 411055, 100, 3 };//according to current contents in shaking.par text file

sp_test = read_shaking_par("testing_fodder/parameters/shaking.par");

fail_unless(compare_shaking_par(sp_test, &sp_correct));

sp_correct.seq_first=0;
fail_if(compare_shaking_par(sp_test, &sp_correct));
}
END_TEST

START_TEST(test_read_compare_mm_np_par)
{
mm_np mm1,mm2;
Expand Down Expand Up @@ -128,8 +142,13 @@ END_TEST

Suite* fb_suite(void) {
Suite *s = suite_create ("Parameters handling");
TCase *tc;

tc=tcase_create ("Read shaking parameters");
tcase_add_test(tc, test_read_shaking_par);
suite_add_tcase (s, tc);

TCase *tc = tcase_create ("Read sequence parameters");
tc = tcase_create ("Read sequence parameters");
tcase_add_test(tc, test_read_sequence_par);
suite_add_tcase (s, tc);

Expand Down
9 changes: 9 additions & 0 deletions py_bind/optv/parameters.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,16 @@ cdef extern from "optv/parameters.h":
double d[3]
double n3
int lut

ctypedef struct shaking_par:
int seq_first
int seq_last
int max_shaking_points
int max_shaking_frames

cdef class MultimediaParams:
cdef mm_np* _mm_np

cdef class ShakingParams:
cdef shaking_par* _shaking_par

63 changes: 62 additions & 1 deletion py_bind/optv/parameters.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
from libc.stdlib cimport malloc, free
import numpy

cdef extern from "optv/parameters.h":
shaking_par * c_read_shaking_par "read_shaking_par"(char * file_name)
int c_compare_shaking_par "compare_shaking_par"(shaking_par * s1, shaking_par * s2)

cdef class MultimediaParams:

def __init__(self, **kwargs):
Expand Down Expand Up @@ -84,4 +88,61 @@ cdef class MultimediaParams:

def __dealloc__(self):
free(self._mm_np)


# Wrapping the shaking_par C struct for pythonic access
# Binding the read_shaking_par C function
# Objects of this type can be checked for equality using "==" and "!=" operators
cdef class ShakingParams:

def __init__(self, seq_first, seq_last, max_shaking_points, max_shaking_frames):
self._shaking_par = < shaking_par *> malloc(sizeof(shaking_par))
self.set_seq_first(seq_first)
self.set_seq_last(seq_last)
self.set_max_shaking_points(max_shaking_points)
self.set_max_shaking_frames(max_shaking_frames)

# Reads shaking parameters from specified full file path
def read_shaking_par(self, file_name):
self._shaking_par = c_read_shaking_par(file_name)

# Checks for equality between this and other ShakingParams objects
# Gives the ability to use "==" and "!=" operators on two ShakingParams objects
def __richcmp__(ShakingParams self, ShakingParams other, operator):
if (operator==2): # "==" action was performed
if (c_compare_shaking_par(self._shaking_par,
other._shaking_par) != 0):
return True
else:
return False
else:
if(operator==3): # "!=" action was performed
return not self==other # change the operator to "==" and recursively check the opposite

# Getters and setters
def get_seq_first(self):
return self._shaking_par[0].seq_first

def set_seq_first(self, seq_first):
self._shaking_par[0].seq_first = seq_first

def get_seq_last(self):
return self._shaking_par[0].seq_last

def set_seq_last(self, seq_last):
self._shaking_par[0].seq_last = seq_last

def get_max_shaking_points(self):
return self._shaking_par[0].max_shaking_points

def set_max_shaking_points(self, max_shaking_points):
self._shaking_par[0].max_shaking_points = max_shaking_points

def get_max_shaking_frames(self):
return self._shaking_par[0].max_shaking_frames

def set_max_shaking_frames(self, max_shaking_frames):
self._shaking_par[0].max_shaking_frames = max_shaking_frames

# Memory freeing
def __dealloc__(self):
free(self._shaking_par)
25 changes: 0 additions & 25 deletions py_bind/test/test_MultimediaParams.py

This file was deleted.

68 changes: 68 additions & 0 deletions py_bind/test/test_parameters_bindings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import unittest
from optv.parameters import MultimediaParams, ShakingParams
import numpy

class Test_Parameters_binding(unittest.TestCase):
def test_mm_np_instantiation(self):

n2_np = numpy.array([11,22,33])
d_np = numpy.array([55,66,77])

m = MultimediaParams(nlay=3, n1=2, n2=n2_np, d=d_np, n3=4, lut=1)

self.failUnlessEqual(m.get_nlay(), 3)
self.failUnlessEqual(m.get_n1(), 2)
self.failUnlessEqual(m.get_n3(), 4)
self.failUnlessEqual(m.get_lut(), 1)

numpy.testing.assert_array_equal(m.get_d(), d_np)
numpy.testing.assert_array_equal(m.get_n2(), n2_np)

self.failUnlessEqual(m.__str__(), "nlay=\t3 \nn1=\t2.0 \nn2=\t{11.0, 22.0, 33.0}"
+ " \nd=\t{55.0, 66.0, 77.0} \nn3=\t4.0 \nlut=\t1 ")

def test_shaking_par_instantiation(self):

# manually assign values to ShakingParams object and check the assignments were made correctly
sp1 = ShakingParams(222, 333, 444, 555)

self.failUnlessEqual(sp1.get_seq_first(), 222)
self.failUnlessEqual(sp1.get_seq_last(), 333)
self.failUnlessEqual(sp1.get_max_shaking_points(), 444)
self.failUnlessEqual(sp1.get_max_shaking_frames(), 555)

# checking C read_shaking_par function
# read shaking parameters from a file and
# verify the parameters were read correctly according to contents of specified file
sp1.read_shaking_par("testing_fodder/parameters/shaking.par")
self.failUnlessEqual(sp1.get_seq_first(), 410000)
self.failUnlessEqual(sp1.get_seq_last(), 411055)
self.failUnlessEqual(sp1.get_max_shaking_points(), 100)
self.failUnlessEqual(sp1.get_max_shaking_frames(), 3)

# manually assigning values exactly like in the shaking parameters testing file
# to another ShakingParams object
sp2 = ShakingParams(410000, 411055, 100, 3)

self.failUnlessEqual(sp2.get_seq_first(), 410000)
self.failUnlessEqual(sp2.get_seq_last(), 411055)
self.failUnlessEqual(sp2.get_max_shaking_points(), 100)
self.failUnlessEqual(sp2.get_max_shaking_frames(), 3)

# now we have two identical ShakingParams objects (sp1 and sp2) for comparison
# PLEASE NOTE that Python will perform the comparison through function defined in ShakingParams class:
# def __richcmp__ (ShakingParams self, ShakingParams other, operator):
# The third parameter is an integer value to indicate the operation performed: 2 for '=' , 3 for '!=' (you must refer to them separately).
# For more info: http://docs.cython.org/src/userguide/special_methods.html#rich-comparisons
# So in order to check the comparisons '==' as well as '!=' must be passed:
self.assertTrue(sp1==sp2)
self.assertFalse(sp1!=sp2)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the difference between this line and the one before? Same for the following occurrence on lines 59-60.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comparison is performed through function defined in ShakingParams:

 def __richcmp__ (ShakingParams self, ShakingParams other, operator):  

The third parameter is integer value to indicate the operation performed: 2 for '=' , 3 for '!=' (you must refer to them separately).
For more info: http://docs.cython.org/src/userguide/special_methods.html#rich-comparisons

So in order to check the comparisons I must pass '==' as well as '!=' .

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. This is not trivial, better add a comment explaining it.


#change one attribute in sp2 and assert the results of equality comparison are now inverted
sp2.set_max_shaking_frames(-999)
self.assertFalse(sp1==sp2)
self.assertTrue(sp1!=sp2)


if __name__ == "__main__":
unittest.main()
4 changes: 4 additions & 0 deletions py_bind/test/testing_fodder/parameters/shaking.par
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
410000
411055
100
3