简体   繁体   English

如何,何时以及在python中进行矢量化的内容?

[英]How, when and what to vectorize in python?

Right, so this is basically a follow up of an earlier question of mine. 是的,所以这基本上是对我早期问题的跟进。 I have some binary data that are in floating point binary format. 我有一些浮点二进制格式的二进制数据。 Using C, the process is fast , but I lose some precision with atof(). 使用C,过程很快 ,但是我用atof()失去了一些精度。 I tried looking through the forum, and also elsewhere, but my problem was not solved. 我试过通过论坛,以及其他地方,但我的问题没有解决。 As such, I moved to python. 因此,我搬到了python。 Ah joy! 啊快乐! the program worked perfectly well, but is so very slow compared to C. I looked up optimizations on python, which pointed me to Cython and Weave, but I have some doubts. 该程序运行得非常好,但与C相比非常慢 。我查找了对python的优化,它指向Cython和Weave,但我有些疑惑。 If you will follow my code, I am confused where to apply the optimizing C code, since I am reading from the numpy object. 如果您将遵循我的代码,我很困惑应用优化C代码的地方,因为我正在读取numpy对象。 My question, is it possible to read data using numpy functions within the Cython, and if so, please provide a small example. 我的问题是,是否可以使用Cython中的numpy函数读取数据,如果是这样,请提供一个小例子。

The C Code uses PolSARpro's header files, and libbmp for creating the .bmp file C代码使用PolSARpro的头文件,使用libbmp创建.bmp文件

As a note, I am posting both my codes. 作为一个说明,我发布了我的代码。 God knows I had to go through a lot just to get the formulas working. 上帝知道我必须经历很多只是为了让公式运转起来。 This way, others in need can give their thoughts and input too :) 这样,有需要的人也可以提出他们的想法和意见:)

C Code (Working, but atof() loses precision, thus output lat long are slightly off) C代码(工作,但atof()失去精度,因此输出lat long略微偏离)


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <polSARpro/bmpfile.c>
#include <polSARpro/graphics.c>
#include <polSARpro/matrix.c>
#include <polSARpro/processing.c>
#include <polSARpro/util.c>
#define METAL_THRESHOLD 5.000000
#define POLARIZATION_FRACTION_THRESHOLD 0.900000
#define PI 3.14159265
#define FOURTHPI PI/4
#define deg2rad PI/180
#define rad2deg 180./PI

/*double PI = 3.14159265;
double FOURTHPI = PI / 4;
double deg2rad = PI / 180;
double rad2deg = 180.0 / PI;*/

FILE *L1,*PF,*SPF;
FILE *txt;
FILE *finalLocations;
long i=0,loop_end;
int lig,col;
float l1,pf,spf;
long pos;
int Nlig,Ncol;

float *bufferout;
float *bufferin_L1,*bufferin_L2;
float valueL1,valuePF,xx;
float sizeGridX, sizeGridY, startX, startY;
float posX,posY;
int ZONE;
char Heading[10];
char setZone[15];

int p[4][2];

int degree, minute, second;

void UTM2LL(int ReferenceEllipsoid, double UTMNorthing, double UTMEasting, char* UTMZone, double *Lat, double *Long)
{
//converts UTM coords to lat/long.  Equations from USGS Bulletin 1532
//East Longitudes are positive, West longitudes are negative.
//North latitudes are positive, South latitudes are negative
//Lat and Long are in decimal degrees.
    //Written by Chuck Gantz- chuck.gantz@globalstar.com

    double k0 = 0.9996;
    double a = 6378137;
    double eccSquared =  0.00669438;
    double eccPrimeSquared;
    double e1 = (1-sqrt(1-eccSquared))/(1+sqrt(1-eccSquared));
    double N1, T1, C1, R1, D, M;
    double LongOrigin;
    double mu, phi1, phi1Rad;
    double x, y;
    int ZoneNumber;
    char* ZoneLetter;
    int NorthernHemisphere; //1 for northern hemispher, 0 for southern

    x = UTMEasting - 500000.0; //remove 500,000 meter offset for longitude
    y = UTMNorthing;

    ZoneNumber = strtoul(UTMZone, &ZoneLetter, 10);
    if((*ZoneLetter - 'N') >= 0)
        NorthernHemisphere = 1;//point is in northern hemisphere
    else
    {
        NorthernHemisphere = 0;//point is in southern hemisphere
        y -= 10000000.0;//remove 10,000,000 meter offset used for southern hemisphere
    }

    LongOrigin = (ZoneNumber - 1)*6 - 180 + 3;  //+3 puts origin in middle of zone

    eccPrimeSquared = (eccSquared)/(1-eccSquared);

    M = y / k0;
    mu = M/(a*(1-eccSquared/4-3*eccSquared*eccSquared/64-5*eccSquared*eccSquared*eccSquared/256));

    phi1Rad = mu    + (3*e1/2-27*e1*e1*e1/32)*sin(2*mu)
                + (21*e1*e1/16-55*e1*e1*e1*e1/32)*sin(4*mu)
                +(151*e1*e1*e1/96)*sin(6*mu);
    phi1 = phi1Rad*rad2deg;

    N1 = a/sqrt(1-eccSquared*sin(phi1Rad)*sin(phi1Rad));
    T1 = tan(phi1Rad)*tan(phi1Rad);
    C1 = eccPrimeSquared*cos(phi1Rad)*cos(phi1Rad);
    R1 = a*(1-eccSquared)/pow(1-eccSquared*sin(phi1Rad)*sin(phi1Rad), 1.5);
    D = x/(N1*k0);

    *Lat = phi1Rad - (N1*tan(phi1Rad)/R1)*(D*D/2-(5+3*T1+10*C1-4*C1*C1-9*eccPrimeSquared)*D*D*D*D/24
                    +(61+90*T1+298*C1+45*T1*T1-252*eccPrimeSquared-3*C1*C1)*D*D*D*D*D*D/720);
    *Lat = *Lat * rad2deg;

    *Long = (D-(1+2*T1+C1)*D*D*D/6+(5-2*C1+28*T1-3*C1*C1+8*eccPrimeSquared+24*T1*T1)
                    *D*D*D*D*D/120)/cos(phi1Rad);
    *Long = LongOrigin + *Long * rad2deg;
}

void convertToDegree(float decimal)
{
    int negative = decimal < 0;
    decimal = abs(decimal);
    minute = (decimal * 3600/ 60);
    second = fmodf((decimal * 3600),60);
    degree = minute / 60;
    minute = minute % 60;
    if (negative)
    {
        if (degree > 0)
            degree = -degree;
        else if (minute > 0)
            minute = -minute;
        else
            second = -second;
    }
}

void readConfig(int *Row, int *Col)
{
    char tmp[70];
    int i=0;
    FILE *fp = fopen("config.txt","r");
    if(fp == NULL)
    {
        perror("Config.txt");
        exit(1);
    }
    while(!feof(fp))
    {
        fgets(tmp,70,fp);
        if (i==1)
            *Row = atoi(tmp);
        if(i==4)
            *Col = atoi(tmp);
        i++;
    }
    fclose(fp);
}

void readHDR(float *gridX,float *gridY,float *startXPos,float *startYPos)
{
    FILE *fp = fopen("PF.bin.hdr","r");
    int i=0;
    char tmp[255];
    char junk[255];
    memset(tmp,0X00,sizeof(tmp));
    memset(junk,0X00,sizeof(junk));
    if(fp==NULL)
    {
        perror("Please locate or create PF.bin.hdr");
        exit(0);
    }
    while(!feof(fp))
    {
        if(i==13)
            break;
        fgets(tmp,255,fp);
        i++;
    }
    fclose(fp);

    strcpy(junk,strtok(tmp,","));
    strtok(NULL,",");
    strtok(NULL,",");
    strcpy(tmp,strtok(NULL,","));
    //puts(tmp);
    *startXPos = atof(tmp);
    strcpy(tmp,strtok(NULL,","));
    //puts(tmp);
    *startYPos = atof(tmp);
    strcpy(tmp,strtok(NULL,","));
    //puts(tmp);
    *gridX = atof(tmp);
    strcpy(tmp,strtok(NULL,","));
    //puts(tmp);
    *gridY = atof(tmp);
    strcpy(tmp,strtok(NULL,","));
    ZONE = atoi(tmp);
    strcpy(tmp,strtok(NULL,","));
    strcpy(Heading,tmp);
}

int main()
{
    bmpfile_t *bmp;
    double Lat;
    double Long;
    int i;
    rgb_pixel_t pixelMetal = {128, 64, 0, 0};
    rgb_pixel_t pixelOthers = {128, 64, 0, 0};
    readConfig(&Nlig,&Ncol);
    readHDR(&sizeGridX,&sizeGridY,&startX,&startY);
    //startX = startX - (double) 0.012000;
    //startY = startY + (double)0.111000;
    printf("Enter the rectangle's top-left and bottom-right region of interest points as: x y\n");
    for(i=0;i<2;i++)
    {
        printf("Enter point %d::\t",i+1);
        scanf("%d %d",&p[i][0], &p[i][1]);
    }
    printf("Grid Size(X,Y)::( %f,%f ), Start Positions(X,Y)::( %f, %f ), ZONE::%d, Heading:: %s\n\n",sizeGridX,sizeGridY,startX,startY,ZONE,Heading);
    pixelMetal.red = 255;
    pixelMetal.blue = 010;
    pixelMetal.green = 010;
    pixelOthers.red = 8;
    pixelOthers.blue = 8;
    pixelOthers.green = 8;
    L1 = fopen("l1.bin","rb");
    PF =fopen("PF.bin","rb");
    SPF = fopen("SPF_L1.bin","wb");
    //txt = fopen("locations(UTM).txt","w");
    finalLocations = fopen("locationsROI.txt","w");
    if(L1==NULL || PF==NULL || SPF==NULL || finalLocations == NULL)
    {
        perror("Error in opening files!");
        return -1;
    }
    fseek(L1,0,SEEK_END);
    pos = ftell(L1);
    loop_end = pos;
    printf("L1.bin contains::\t%ld elements\n",pos);
    fseek(PF,0,SEEK_END);
    pos = ftell(PF);
    printf("PF.bin contains::\t%ld elements\n",pos);
    fseek(L1,0,SEEK_SET);
    fseek(PF,0,SEEK_SET);
    bmp = bmp_create(Ncol,Nlig,8); //width * height
    bufferin_L1 = vector_float(Ncol);
    bufferin_L2 = vector_float(Ncol);
    bufferout = vector_float(Ncol);
    printf("Resources Allocated. Beginning...\n");
    for (lig = 0; lig < Nlig; lig++) /* rows */
    {
        if (lig%(int)(Nlig/20) == 0)
        {
            printf("%f\r", 100. * lig / (Nlig - 1));
            fflush(stdout);
        }
        fread(&bufferin_L1[0], sizeof(float), Ncol, L1);
        fread(&bufferin_L2[0], sizeof(float), Ncol, PF);
        for (col = 0; col < Ncol; col++) /* columns */
        {
            valueL1 = bufferin_L1[col];
            valuePF = bufferin_L2[col];
            if(valueL1 >= METAL_THRESHOLD && valuePF >= POLARIZATION_FRACTION_THRESHOLD)
            {
                if(col >= p[0][0] && col <= p[1][0] && lig >= p[0][1] && lig <= p[1][1])
                {
                    xx = fabs(valueL1 + valuePF);
                    bmp_set_pixel(bmp,col,lig,pixelMetal);
                    posX = startX + (sizeGridX * col);
                    posY = startY - (sizeGridY * lig);
                    //fprintf(txt,"%f %f %d %s\n",posX,posY,ZONE,Heading);
                    sprintf(setZone,"%d",ZONE);
                    if(strstr(Heading,"Nor")!=NULL)
                        strcat(setZone,"N");
                    else
                        strcat(setZone,"S");
                    UTM2LL(23, posY, posX, setZone, &Lat, &Long); // 23 for WGS-84
                    convertToDegree(Lat);
                    //fprintf(finalLocations,"UTM:: %.2fE %.2fN , Decimal: %f %f , Degree: %d %d %d, ",posX,posY,Lat,Long,degree,minute,second);
                    //fprintf(finalLocations,"%.2fE,%.2fN,%f,%f ,%d,%d,%d,",posX,posY,Lat,Long,degree,minute,second);
                    fprintf(finalLocations,"%.2f,%.2f,%f,%f ,%d,%d,%d,",posX,posY,Lat,Long,degree,minute,second);
                    convertToDegree(Long);
                    fprintf(finalLocations,"%d,%d,%d\n",degree,minute,second);
                }
                else
                {
                    xx = fabs(valueL1) ;
                    bmp_set_pixel(bmp,col,lig,pixelOthers);
                }
            }
            else
            {
                xx = fabs(valueL1) ;
                bmp_set_pixel(bmp,col,lig,pixelOthers);
            }
            bufferout[col] = xx;
        }
        fwrite(&bufferout[0], sizeof(float), Ncol, SPF);
    }
    free_vector_float(bufferout);
    fclose(L1);
    fclose(PF);
    fclose(SPF);
    //fclose(txt);
    fclose(finalLocations);
    printf("\n----------Writing BMP File!----------\n");
    bmp_save(bmp,"SPF_L1(ROI).bmp");
    bmp_destroy(bmp);
    printf("\nDone!\n");
}

As well as the Python code:: 以及Python代码::


# -*- coding: utf-8 -*-
"""
Created on Wed Apr 10 10:29:18 2013

@author: Binayaka
"""
import numpy as Num;
import math;
import array;

class readConfiguration(object):  

    def __init__(self,x):
        self.readConfig(x);

    def readConfig(self,x):
        try:
            crs = open(x,'r');
            srs = open('config.txt','r');
        except IOError:
            print "Files missing!";
        else:
            rows = crs.readlines();                
            values = rows[12].split(',');
            rows = srs.readlines();                
            self.startX = float(values[3]);
            self.startY = float(values[4]);
            self.gridSizeX = float(values[5]);
            self.gridSizeY = float(values[6]);
            self.Zone = int(values[7]);
            self.Hemisphere = values[8];
            self.NRows = int(rows[1].strip());
            self.NCols = int(rows[4].strip());
            self.MetalThreshold = 5.000000;
            self.PFThreshold = 0.900000;
            self.rad2deg = 180/math.pi;
            self.deg2rad = math.pi/180;
            self.FOURTHPI = math.pi/4;
            crs.close();
            srs.close();

    def decdeg2dms(dd):
        negative = dd < 0;
        dd = abs(dd);
        minutes,seconds = divmod(dd*3600,60);
        degrees,minutes = divmod(minutes,60);
        if negative:
            if degrees > 0:
                degrees = -degrees;
            elif minutes > 0:
                    minutes = -minutes;
        else:
            seconds = -seconds;
        return (degrees,minutes,seconds);

    def UTM2LL(self,UTMEasting, UTMNorthing):
        k0 = 0.9996;
        a = 6378137;
        eccSquared =  0.00669438;
        e1 = (1-math.sqrt(1-eccSquared))/(1+math.sqrt(1-eccSquared));
        x = UTMEasting - 500000.0;#remove 500,000 meter offset for longitude
        y = UTMNorthing;
        if self.Hemisphere == "North":
            self.Hemi = 1;
        else:
            self.Hemi = -1;
            y -= 10000000.0;
        LongOrigin = (self.Zone - 1)*6 - 180 + 3;
        eccPrimeSquared = (eccSquared)/(1-eccSquared);
        M = y / k0;
        mu = M/(a*(1-eccSquared/4-3*eccSquared*eccSquared/64-5*eccSquared*eccSquared*eccSquared/256));
        phi1Rad = mu    + (3*e1/2-27*e1*e1*e1/32)*math.sin(2*mu) + (21*e1*e1/16-55*e1*e1*e1*e1/32)*math.sin(4*mu) +(151*e1*e1*e1/96)*math.sin(6*mu);
        #phi1 = phi1Rad*self.rad2deg;
        N1 = a/math.sqrt(1-eccSquared*math.sin(phi1Rad)*math.sin(phi1Rad));
        T1 = math.tan(phi1Rad)*math.tan(phi1Rad);
        C1 = eccPrimeSquared*math.cos(phi1Rad)*math.cos(phi1Rad);
        R1 = a*(1-eccSquared)/pow(1-eccSquared*math.sin(phi1Rad)*math.sin(phi1Rad), 1.5);
        D = x/(N1*k0);
        self.Lat = phi1Rad - (N1*math.tan(phi1Rad)/R1)*(D*D/2-(5+3*T1+10*C1-4*C1*C1-9*eccPrimeSquared)*D*D*D*D/24   +(61+90*T1+298*C1+45*T1*T1-252*eccPrimeSquared-3*C1*C1)*D*D*D*D*D*D/720);
        self.Lat = self.Lat * self.rad2deg;
        self.Long = (D-(1+2*T1+C1)*D*D*D/6+(5-2*C1+28*T1-3*C1*C1+8*eccPrimeSquared+24*T1*T1)*D*D*D*D*D/120)/math.cos(phi1Rad);
        self.Long = LongOrigin + self.Long * self.rad2deg;   

    def printConfiguration(self):        
        """ Just to check whether our reading was correct """
        print "Metal Threshold:\t" + str(self.MetalThreshold);        
        print "PF    Threshold:\t" + str(self.PFThreshold);
        print "Start         X:\t" + str(self.startX);
        print "Start         Y:\t" + str(self.startY);
        print "Grid size(X)   :\t" + str(self.gridSizeX);
        print "Grid size(Y)   :\t" + str(self.gridSizeY);

    def createROIfile(self,ROIFilename):
        firstPoint = raw_input('Enter topLeft point coord\t').split();
        secondPoint = raw_input('Enter bottomRight point coord\t').split();
        try:
            L1 = open('l1.bin','rb');
            PF = open('PF.bin','rb');
            SPF = open('pySPF_L1.bin','wb');
            targetFilename = open(ROIFilename,'w');
        except IOError:
            print "Files Missing!";
        else:
            L1.seek(0,2);
            elementsL1 = L1.tell();
            L1.seek(0,0);
            PF.seek(0,2);
            elementsPF = PF.tell();
            PF.seek(0,0);
            print "L1.bin contains\t" + str(elementsL1) + " elements";
            print "PF.bin contains\t" + str(elementsPF) + " elements";
            binvaluesL1 = array.array('f');
            binvaluesPF = array.array('f');
            binvaluesSPF = array.array('f');            
            for row in range(0,self.NRows):                                
                binvaluesL1.read(L1,self.NCols);
                binvaluesPF.read(PF,self.NCols);
                dataL1 = Num.array(binvaluesL1, dtype=Num.float);
                dataPF = Num.array(binvaluesPF, dtype=Num.float);
                dataSPF = dataL1 + dataPF;
                binvaluesSPF.fromlist(Num.array(dataSPF).tolist());                                
                for col in range(0,self.NCols):                     
                    if(dataL1[col] >= self.MetalThreshold and dataPF[col] >= self.PFThreshold):
                        if(col >= int(firstPoint[0]) and col <= int(secondPoint[0]) and row >= int(firstPoint[1]) and row <= int(secondPoint[1])):
                            posX = self.startX + (self.gridSizeX * col);                         
                            posY = self.startY - (self.gridSizeY * row);
                            self.UTM2LL(posY,posX);
                            tmp1 = self.decdeg2dms(posY);
                            tmp2 = self.decdeg2dms(posX);
                            strTarget = "Decimal Degree:: " + str(posX) + "E " + str(posY) + "N \t Lat long:: " + str(tmp1) + " " + str(tmp2) + "\n";
                            targetFilename.write(strTarget);
                binvaluesSPF.tofile(SPF);
            L1.close();
            PF.close();
            SPF.close();
            targetFilename.close();
            print "Done!";

dimensions = readConfiguration('PF.bin.hdr');
dimensions.printConfiguration();
dimensions.createROIfile('testPythonROI.txt');

Its the Python code that needs Optimization, as the values of NRows and NCols can and do reach the order of thousands. 它是需要优化的Python代码,因为NRows和NCols的值可以达到数千个数量级。

A few general comments: 一些一般性评论:

  1. With python, it's really best to stick to PEP8 for a multitude of reasons. 使用python,出于多种原因,最好坚持使用PEP8 Python programmers are particularly picky about readability and essentially universally adhere to the community coding guidelines (PEP8). Python程序员对可读性特别挑剔,并且基本上普遍遵守社区编码指南(PEP8)。 Avoid camelCase, keep lines below 80 columns, leave the semicolons out, and feel free to occasionally ignore these guidelines where they'd make things less readable. 避免使用camelCase,将行保留在80列以下,留下分号,并随意忽略这些指导原则,因为它们会降低可读性。

  2. There's no need for the builtin array type here if you're using numpy. 如果你正在使用numpy,那么这里不需要内置array类型。 I'm confused why you're constantly converting back and forth... 我很困惑为什么你经常来回转换......

  3. Use a projection library. 使用投影库。 Specify what datum and ellipsoid you're using, otherwise the coordinates (easting/northing or lat/long) have absolutely no meaning. 指定您正在使用的基准面和椭球面,否则坐标(东/北或纬度/长度)绝对没有意义。

  4. Don't use one big class as a hold-all for unrelated things. 不要使用一个大班作为不相关的东西。 There's nothing wrong with just having a few functions. 只有一些功能没有错。 You don't need to make it into a class unless it makes sense to do so. 除非有意义,否则你不需要把它变成一个类。

  5. Use vectorized operations with numpy arrays. 使用numpy数组的矢量化操作。

Here's what would appear to be your performance bottleneck: 这似乎是您的性能瓶颈:

    for row in range(0,self.NRows):                                
        binvaluesL1.read(L1,self.NCols);
        binvaluesPF.read(PF,self.NCols);
        dataL1 = Num.array(binvaluesL1, dtype=Num.float);
        dataPF = Num.array(binvaluesPF, dtype=Num.float);
        dataSPF = dataL1 + dataPF;
        binvaluesSPF.fromlist(Num.array(dataSPF).tolist());                                
        for col in range(0,self.NCols):                     
            if(dataL1[col] >= self.MetalThreshold and dataPF[col] >= self.PFThreshold):
                if(col >= int(firstPoint[0]) and col <= int(secondPoint[0]) and row >= int(firstPoint[1]) and row <= int(secondPoint[1])):
                    posX = self.startX + (self.gridSizeX * col);                         
                    posY = self.startY - (self.gridSizeY * row);
                    self.UTM2LL(posY,posX);
                    tmp1 = self.decdeg2dms(posY);
                    tmp2 = self.decdeg2dms(posX);
                    strTarget = "Decimal Degree:: " + str(posX) + "E " + str(posY) + "N \t Lat long:: " + str(tmp1) + " " + str(tmp2) + "\n";
                    targetFilename.write(strTarget);
        binvaluesSPF.tofile(SPF);

One of your biggest problems is the way you're reading in your data. 您最大的问题之一是您阅读数据的方式。 You're constantly reading things in as one thing, then converting that to a list, then converting that to a numpy array. 你经常读东西,然后将其转换为列表,然后将其转换为numpy数组。 There's absolutely no need to jump through all those hoops. 绝对没有必要跳过所有这些篮球。 Numpy will unpack your binary floats for you just like array will. Numpy会为你解压缩二进制浮点数就像array一样。

Just do grid = np.fromfile(yourfile, dtype=np.float32).reshape(ncols, nrows) . 只需要执行grid = np.fromfile(yourfile, dtype=np.float32).reshape(ncols, nrows) (Outside the loop.) (在循环之外。)

After that, your nested loops can be easily vectorized and expressed with just a few lines of code. 之后,您可以轻松地对嵌套循环进行矢量化,并使用几行代码表示。

Here's how I would write your code. 这是我编写代码的方式。 This probably won't run as-is, as I can't test it with your data. 这可能不会按原样运行,因为我无法使用您的数据进行测试。 However, it should give you some general ideas. 但是,它应该给你一些一般性的想法。

import numpy as np
import pyproj

def main():
    config = Config('PF.bin.hdr')
    grid1, grid2 = load_data('l1.bin', 'PF.bin', config.nrows, config.ncols)

    spf = grid1 + grid2
    spf.tofile('pySPF_L1.bin')

    easting_aoi, northing_aoi = subset_data(grid1, grid2, config)
    save_selected_region(easting_aoi, northing_aoi, config.zone, 
                        'testPythonROI.txt')

def load_data(filename1, filename2, nrows, ncols):
    """It would really be good to use more descriptive variable names than "L1"
    and "PF".  I have no idea what L1 and PF are, so I'm just calling them
    grid1 and grid2."""
    grid1 = np.fromfile(filename1, dtype=np.float32).reshape(nrows, ncols)
    grid2 = np.fromfile(filename2, dtype=np.float32).reshape(nrows, ncols)
    return grid1, grid2

def subset_data(grid1, grid2, config):
    """Select points that satisfy some threshold criteria (explain??) and are
    within a user-specified rectangular AOI."""
    northing, easting = np.mgrid[:config.nrows, :config.ncols]
    easting = config.xstart + config.xgridsize * easting
    northing = config.ystart + config.ygridsize * northing

    grids = grid1, grid2, easting, northing
    grid1, grid2, easting, northing = [item[config.user_aoi] for item in grids]

    mask = (grid1 >= config.metal_threshold) & (grid2 >= config.pf_threshold)
    return easting[mask], northing[mask]

def save_selected_region(easting, northing, zone, filename):
    """Convert the given eastings and northings (in UTM zone "zone") to 
    lat/long and save to a tab-delimited-text file."""
    lat, lon = utm2geographic(easting, northing, zone)
    data = np.vstack([easting, northing, lat, lon]).T
    with open(filename, 'w') as outfile:
        outfile.write('Easting\tNorthing\tLatitude\tLongitude\n')
        np.savetxt(outfile, data, delimiter='\t')

def utm2geographic(easting, northing, zone):
    """We need to know which datum/ellipsoid the UTM coords are in as well!!!!
    I'm assuming it's a Clark 1866 ellipsoid, based on the numbers in your
    code..."""
    utm = pyproj.Proj(proj='utm', zone=zone, ellip='clrk66')
    geographic = pyproj.Proj(proj='latlong', ellip='clrk66')
    return pyproj.transform(utm, geographic, easting, northing)

class Config(object):
    """Read and store configuration values for (something?)."""
    config_file = 'config.txt'
    def __init__(self, filename):
        """You should add docstrings to clarify what you're expecting 
        "filename" to contain."""
        with open(filename, 'r') as infile:
            crs_values = list(infile)[12].split(',')
        crs_values = [float(item) for item in crs_values]
        self.xstart, self.ystart = crs_values[3:5]
        self.xgridsize, self.ygridsize = crs_values[5:7]
        self.zone = int(crs_values[7])

        with open(self.config_file, 'r') as infile:
            srs_values = list(infile)
        self.nrows, self.ncols = srs_values[1], srs_values[4]

        # It would be good to explain a bit about these (say, units, etc)
        self.metal_threshold = 5.0
        self.pf_threshold = 0.9

        self.user_aoi = self.read_user_aoi()

    def read_user_aoi(self):
        """Get an area of interest of the grids in pixel coordinates."""
        top_left = raw_input('Enter top left index\t')
        bottom_right = raw_input('Enter bottom right index\t')
        min_i, min_j = [int(item) for item in top_left.split()]
        max_i, max_j = [int(item) for item in bottom_right.split()]
        return slice(min_i, max_i), slice(min_j, max_j)

if __name__ == '__main__':
    main()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM