EMAN2: Developer's FAQ
As a redesign based on EMAN1, EMAN2 is more object-oriented, and
is
more modular, and is designed to be easier to use for both regular
users and developers.
- How to
read/write an image in python?
- #
to convert from IMAGIC to MRC or SPIDER:
from
EMAN2 import *
e =
EMData()
e.read_image(“proj.img”)
e.write_image(“proj.mrc”)
# output image format is determined by
file extension
e.write_image(“proj.spi”,
1,
SPIDER) # explicitly specifiy the output image
format
- How to
add a processor?
- EMAN2
standard coding style
- How to
define a XYZProcessor?
- Processor
naming convention: more generic word goes first. e.g.
LowpassGaussProcessor, HighpassGaussProcessor.
-
/* 1)
Replace all 'XYZ' with
your new processor name.
*
2) Define the processor
parameter names and types in get_param_types().
*
3) Implement the
processor in XYZProcessor::process().
*/
class
XYZProcessor : public
Processor {
public:
void
process(EMData *image);
string
get_name() const { return "XYZ"; }
static
Processor *NEW() { return new XYZProcessor(); }
TypeDict
get_param_types() const {
TypeDict d;
d.put("value1", EMObject::INT);
d.put("value2", EMObject::FLOAT);
return d;
}
};
- How to
use a Processor in python?
-
from
EMAN2 import *
e =
EMData()
e.read_image("test1.mrc")
e.process_inplace("math.sqrt")
e.process_inplace("threshold.binaryrange", {"low" :5.2, "high" : 10})
e.write_image("output.mrc")
For out of place processing:
f = e.process("math.sqrt")
f.write_image("output.mrc")
- How to
Use a Reconstructor in python?
- from EMAN2 import *
import math
e1 = EMData()
e1.read_image(TestUtil.get_debug_image("samesize1.mrc"))
e2 = EMData()
e2.read_image(TestUtil.get_debug_image("samesize2.mrc"))
r =
Reconstructors.get("back_projection")
r.set_params({"size":100,
"weight":1})
r.setup()
r.insert_slice(e1,
Transform(EULER_EMAN, 0,0,0))
r.insert_slice(e2,
Transform(EULER_EMAN, math.pi/2,0,0))
result = r.finish()
result.write_image("reconstructor.mrc")
- How to
show all Processors?
-
from
EMAN2 import *
dump_processors()
- How to
use boost python?
- EMAN2 use Pyste to
automatically parse the C++ code to generate
boost python wrapper. To use Pyste,
- How to
use Factory classes
like Processor, Aligner, Averager, Cmp, Projector, Reconstructor?
- EMAN has many functions that implement specific algorithms to
do image processing. These algorithms are relatively independent
and a user chooses which one to use. In EMAN2, we define a Factory
class to manage these algorithms, including
- Processor (image
processor)
- Aligner (2D/3D image
alignment)
- Averager (averaging a
set of images)
- Cmp (comparing 2
same-size Images)
- Projector (3D image
projection)
- Reconstructor (3D
image reconstruction)
- How to define/use a
XYZProcessor
- Processor is the base class. XYZProcessor
should extend Processor or a
subclass of Processor.
- processors are identified by names. XYZProcessor's name should be
"XYZ" for consistency.
- XYZProcessor must
define
a static function to construct a new
XYZProcessor instance. This function is going to be stored in the
Processor
Factory.
- To use XYZProcessor:
EMData* img1 = ...;
img1->processor("XYZ");
- How to use the Factory
template
- template<>
Factory<Processor>::Factory()
{
add(&AbsoluateValueProcessor::NEW);
add(&GaussLowpassProcessor::NEW);
}
Processor *abs_processor =
Factory<Processor>::get("AbsoluateValue");
Processor
*gauss_lowpass_processor =
Factory<Processor>::get("LowpassGauss",
Dict("lowpass", 12);
- How to
use FFTW library?
- EMAN2 works with both fftw2
and fftw3. A user makes the
choice
at compile time.
- A standard interface is defined to do fft:
- class EMfft {
public:
static
int
real_to_complex_1d(float *real_data, float *complex_data, int n);
static
int
complex_to_real_1d(float *complex_data, float *real_data, int n);
static
int
real_to_complex_nd(float *real_data, float *complex_data, int nx, int
ny, int nz);
static
int
complex_to_real_nd(float *complex_data, float *real_data, int nx, int
ny, int nz);
};
- How to
handle image data
byte-order?
- ByteOrder class is
defined to handle data byte-orders:
- check running-host byte-order;
- check a given data-block byte-order;
- convert host byte-order to little-endian or big-endian
- swap byte-orders
- How to
handle large-file
(>2G) IO?
- portable_fseek() should
be used for fseek.
- portable_ftell() should
be used for ftell.
- How to
use Euler Angles?
- Euler angles are implemented in Rotation class.
- Rotation r =
Rotation(alt, az, phi, Rotation::EMAN);
float alt2 = r.eman_alt();
float az2 = r.eman_az();
float phi2 = r.eman_phi();
float theta = r.mrc_theta();
float phi = r.mrc_phi();
float omega = r.mrc_omega();
- How to
use numpy?
- In EMAN2,
numpy array and the corresponding EMData object shares the same
memory block.
- From
EMData object to numpy array:
from
EMAN2 import *
e
= EMData()
e.read_image("e.mrc"))
array
= EMNumPy.em2numpy(e)
- From
Numerc numpy array to EMData object:
from
EMAN2 import *
import
numpy
n
= 100
numbers
= range(2*n*n)
array
= numpy.reshape(numpy.array(numbers, numpy.Float32), (2*n, n))
e = EMNumpy.numpy2em(array)
e.write_image("numpy.mrc")
- How to
use
Exception handling in EMAN2?
- Here is an example on throwing an
exception:
vector < float
>EMData::calc_fourier_shell_correlation(EMData * with)
{
if (!with)
{
throw NullPointerException("NULL
input image");
}
if
(!EMUtil::is_same_size(this, with)) {
LOGERR("images not same size");
throw ImageFormatException(
"images not same size");
}
//...
}
<>Here is an example on catching
the exceptions:
void foo()
{
EMData*
e1 = new EMData();
EMData*
e2 = new EMData();
try {
e1->read_image("test1.mrc");
e2->read_image("test2.mrc");
vector<float> v =
e1->calc_fourier_shell_correlation(e2);
}
catch (_NullPointerException &
null_excp) {
printf("%s\n",
null_excp.what());
// do something
}
catch
(E2Exception & exception) {
printf("%s\n", exception.what());
}
}
- NOTE: A XYZ exception is
thrown as XYZException, but caught as _XYZException. Be aware of the
"_".
- For the possible Exception types.
please refer the EMAN2 code
in "exception.h".
- How to
use
Transformation?
- * Transform
defines a transformation, which can be rotation,
* translation, scale, and their combinations.
*
* Internally a transformation is stored in a
4x3 matrix.
* a b c
* e f g
* i j k
* m n o
*
* The left-top 3x3 submatrix
* a b c
* e f g
* i j k
* provides rotation, scaling and skewing.
*
* post translation is stored in (m,n,o).
*
* a separate vector containing the
pretranslation, with an implicit
* column [0 0 0 1] at the end when 4x4
multiplies are required.
*
* The 'center of rotation' is NOT implemented
as a separate vector,
* but as a combination of pre and post
translations.
14. How
to print out
error/warning/debugging information?
- use Log class.
- Why use Log
class?
- It defines a
generic way to do logging. The logging may go to either standard out,
a file, or a pipe.
- It may give you best performance. Log functions are defined
as macros. With an option to define all macros to be void, we may make
the program completely silient and remove all the IO overhead.
- It allows different level of verbosity from 0-4, with 0 means
completely silient, 4 means very verbose.
- How to use
Log
1) in your main() file, set log level: Log::logger()->set_log_level(WARNING_LOG);
2) log message in different levels: (log functions use the same
argument format like printf()).
LOGERR("out
of memory");
LOGWARN("invalid
image size");
LOGDEBUG("image
mean density = %f\n", mean);
LOGVAR("image
size = (%d, %d, %d)\n", nx, ny, nz);
3) To log function enter point, use ENTERFUNC; To log function exit
point, use EXITFUNC.
15. How to add testing group tag
for file/class/function?
- These group tags are already
defined in file, "eman2doc.h":
- tested0 : code not yet complete
- tested1 : code complete but untested
- tested2 : code complete but contains bugs
- tested3 : tested
- tested3a : manual testing
- tested3b : unit test in C++
- tested3c : unit test in Python
- tested3d : incorporated into sucessful regression test
- How to use these tag to label
testing group:
- add /**@ingroup tested3c*/ to the beginnig of a class tested
in Python, then the corresponding class will be labeled "unit test in
Python" in doxygen generated documet.
- you can also define other grouping tag, just follow the
testing group example in "eman2doc.h"
- a single unit can be labeled for multiple group
Last modified on 02/14/2007
by Grant Tang
(gtang@bcm.edu)