Beispiel #1
0
def get_state_mask(state_guide, state_color):
    # Get a mask of all pixels of the border key color.
    # Running two_d_array == value produces a 'mask' where only individual pixels are compared, but we want to know about cases where all three pixels are equal.
    # logical_and does this sort of thing, apparently.
    border_mask = logical_and.reduce(state_guide == state_color, axis=-1)

    x_min, y_min, x_max, y_max = find_bounds(border_mask)
    guide_view = state_guide[y_min:y_max + 1, x_min:x_max + 1]

    # Crop the border_mask too.
    border_mask = border_mask[y_min:y_max + 1, x_min:x_max + 1]

    # Create a copy of the border mask with a new layer of false pixels all around the edge.
    state_mask = border_mask.copy()
    state_mask = numpy.insert(state_mask, 0, False, axis=0)
    state_mask = numpy.insert(state_mask, 0, False, axis=1)
    state_mask = numpy.insert(state_mask, state_mask.shape[0], False, axis=0)
    state_mask = numpy.insert(state_mask, state_mask.shape[1], False, axis=1)

    # Get a mask of all pixels outside the state's borders, by performing a flood from the top-left pixel on the expanded mask we've made.
    # Then invert the mask. All true values on the mask signify a point on or within the state's borders.
    state_mask = ~flood(state_mask, (0, 0), connectivity=1)

    # Crop the state_mask back to the bounds of the relevant pixels.
    state_mask = numpy.delete(state_mask, state_mask.shape[0] - 1, 0)
    state_mask = numpy.delete(state_mask, state_mask.shape[1] - 1, 1)
    state_mask = numpy.delete(state_mask, 0, 0)
    state_mask = numpy.delete(state_mask, 0, 1)

    state_mask = state_mask & logical_or.reduce(guide_view != ignore_col,
                                                axis=-1)

    return state_mask, border_mask, x_min, y_min, x_max, y_max
Beispiel #2
0
def split_data_col(data_col):
    """Returns xx, xy, yx, yy, num_pol"""
    flags = logical_or.reduce(data_col.mask, axis = 2)
    
    return (ma.array(data_col[:,:,0], mask=flags),
            ma.array(data_col[:,:,1], mask=flags),
            ma.array(data_col[:,:,-2], mask=flags),
            ma.array(data_col[:,:,-1], mask=flags),
            data_col.shape[-1])
Beispiel #3
0
 def Common(self, i):
     cands = self.Cands[i]
     std = self.Std(i)
     if cands:
         s = array(cands[0])
         s[logical_or.reduce(cands != s)] = Picross.init
         if (std != s).any():
             return Picross.HINT, s
         else:
             return Picross.NORMAL, None
     else:
         return Picross.ILLEGAL, None
Beispiel #4
0
    def run(self):

        m = fabio.open(self.mask).data
        ai = pyFAI.load(self.poniname)
        alpha = float(75)  #In degrees

        x0 = ai.poni1 / ai.pixel1
        y0 = ai.poni2 / ai.pixel2
        dy = 1479 - x0
        dx = 1675 - y0

        tang = tan((90.0 - alpha) / 2.0 * pi / 180.0)

        y = 1479 - dy - x0 * tang
        y = dy + x0 * tang
        x = 1675 - dx - y0 * tang

        # so the points on the edge are
        # (x0,0), (0,y0)
        # which is shorter?

        d1x = (x0 - x)
        d1y = (y0)
        d2y = (y0 - y)
        d2x = (x0)

        l1 = sqrt(d1x * d1x + d1y * d1y)
        l2 = sqrt(d2x * d2x + d2y * d2y)

        # print x0,y0,x,y,tang

        # take off 5 pixels near the edge
        self.radial_mask(m, min(l1, l2) - 5, (x0, y0))
        self.angle_mask(m, tang, (x0, y0))
        self.block_mask(m, tang, (x0, y0))

        mask = logical_or.reduce((self.rmask, self.amask, self.bmask, m))
        #mask=np.logical_or.reduce((rmask,amask,m))
        outfile = 'PDFmask_%.1fdeg.cbf' % (alpha)
        outbuffer = fabio.cbfimage.cbfimage(data=mask)
        outbuffer.write(outfile)
        print('Wrote mask to', outfile)

        perm = 'chmod 777 %s' % self.outfile
        system(perm)
def pixel_correction(im):
    """Correct with interpolation for NaN, Inf, dead and hot pixels.

	Parameters
	----------
	im : array_like
		Image data as numpy array. 

	Return
	----------
	im : array_like
		Image data as numpy array with the correction applied.

	"""
    # Save original type to further re-cast:
    t = im.dtype
    im = im.astype(float32)

    # Flat:
    im_f = im.flatten().astype(float32)

    # Correct for NaNs, Infs, dead, hot:
    try:
        val, x = logical_or.reduce((isnan(im_f), isinf(im_f), (im_f < finfo(float32).eps))), \
           lambda z: z.nonzero()[0]
        im_f[val] = interp(x(val), x(~val), im_f[~val])

    except:
        pass

    finally:

        # Reshape:
        im_f = reshape(im_f, (im.shape[1], im.shape[0]), order='F')
        im_f = im_f.T

    # Re-cast and return:
    return im_f.astype(t)
Beispiel #6
0
	def run_corda(self, rx_cat, constraint, constrainby, nl, ntimes, om=1e4, pr_to_np=2, threads=cpu_count()-1):
		def _corda_find_all_dependencies(reaction_list):
			res_map = {r:i for i,r in enumerate(reaction_list)}
			true_threads = min((len(reaction_list)//2)+1, threads)
			result = [None] * len(reaction_list)
			rx_per_job = len(reaction_list) // threads
			pool = _ProcessPool(
				processes=true_threads,
				initializer=_init_corda_worker,
				initargs=(self.corso_fba, constraint, constrainby, costfx, costbase, ntimes, 1e-6, self.lb)
			)
			for i, value in pool.imap_unordered(_corda_dependent_reactions_iteration, reaction_list,
												chunksize=rx_per_job):
				result[res_map[i]] = value

			pool.close()
			pool.join()

			return result

		import pandas as pd

		rx_cat = array(rx_cat)
		costbase = zeros(self._n, )

		print(pd.Series(rx_cat).value_counts())

		costbase[rx_cat == 2] = sqrt(om)
		costbase[rx_cat == 3] = om

		costfx = self.costfx_factory(nl, om, costbase)

		def nested_dependent_rxs(rx):
			return self.find_dependent_reactions(rx, constraint, constrainby, costfx, costbase, ntimes, eps=1e-6)

		HC_reactions = where(rx_cat == 1)[0]

		print('Step 1 started')
		s1t = time()


			# print(sum(dep),pd.Series(rx_cat).value_counts())
		if (threads and threads > 1) and (len(HC_reactions)/2 > threads):
			res1 = _corda_find_all_dependencies(HC_reactions)
		else:
			res1 = list(map(nested_dependent_rxs, HC_reactions))

		s1_deps, s1_block = list(zip(*res1))
		rx_cat[logical_or.reduce(s1_deps)] = 1
		if sum(s1_block) > 0:
			rx_cat[HC_reactions[s1_block]] = -1

		print('\t- Finished in ',str(time()-s1t),'seconds')
		print(pd.Series(rx_cat).value_counts())
		# for rx in HC_reactions:
		# 	dep, to_del = self.find_dependent_reactions(rx, constraint, constrainby, costfx, costbase, ntimes, eps=1e-6)
		# 	rx_cat[dep] = 1
		# 	if to_del:
		# 		rx_cat[rx] = -1

		self.block_reactions_from_idxs(rx_cat)


		costbase = zeros(self._n, )
		costbase[rx_cat == 3] = om

		PR_reactions = where(rx_cat == 2)[0]
		NP_reactions = where(rx_cat == 3)[0]

		costfx = self.costfx_factory(nl, om, costbase)

		print('Step 2 started')
		s1t = time()
		PR_NP = {}

		# def _step_two(rx):
		# 	dep, to_del = self.find_dependent_reactions(rx, constraint, constrainby, costfx, costbase, ntimes, eps=1e-6)
		# 	PR_NP[rx] = dep[NP_reactions]
		# 	if to_del:
		# 		rx_cat[rx] = -1

		if (threads and threads > 1) and (len(PR_reactions)/2 > threads):
			res2 = _corda_find_all_dependencies(PR_reactions)
		else:
			res2 = list(map(nested_dependent_rxs, PR_reactions))

		s2_deps, s2_block = list(zip(*res2))

		for rx, dep in zip(PR_reactions, s2_deps):
			PR_NP[rx] = dep[NP_reactions]

		if sum(s2_block) > 0:
			rx_cat[PR_reactions[s2_block]] = -1

		print('\t- Finished in ',str(time()-s1t),'seconds')
		print(pd.Series(rx_cat).value_counts())

		self.block_reactions_from_idxs(rx_cat)

		PR_NP = [PR_NP[k] for k in sorted(PR_NP.keys()) if rx_cat[k] != -1]

		if len(PR_NP) > 0:
			PR_NP = vstack(PR_NP)
			NP_occurrence = apply_along_axis(sum, 0, PR_NP)
			np_to_pr_idx = NP_reactions[NP_occurrence > pr_to_np]

			if len(np_to_pr_idx) > 0:
				rx_cat[np_to_pr_idx] = 2
				PR_NP = PR_NP[:, NP_occurrence > pr_to_np]
				if PR_NP.shape[1] > 0:
					PR_NP = vstack([zeros((len(np_to_pr_idx), PR_NP.shape[1]))])
				else:
					PR_NP = array([])

		# 2.2
		PR_reactions = where(rx_cat == 2)[0]
		NP_reactions = where(rx_cat == 3)[0]

		PR_to_check_l8r = []
		rx_cat[NP_reactions] = -1
		self.block_reactions_from_idxs(rx_cat)

		res2 = []
		for i, rx in enumerate(PR_reactions):
			to_del = self.check_if_blocked(rx)
			if to_del:
				# PR_to_check_l8r.append(rx)
				# if len(PR_NP) > 0 and len(np_to_pr_idx) > 0:
				# 	np_from_rx = where(PR_NP[i, :] > 0)[0]
				# 	if len(np_from_rx) == 0:
				# 		print('Undefined')
				# 	else:
				# 		for kn in np_from_rx:
				# 			res2.append(kn)
				rx_cat[rx] = -1
		res2 = unique(sorted(array(res2)))

		PR_reactions = where(rx_cat == 2)[0]
		rx_cat[PR_reactions] = 1
		# rescued = set(sorted(PR_to_check_l8r + res2.tolist()))

		ES_reactions = rx_cat == 1
		OT_reactions = rx_cat == 0

		#to_block = where(ES_reactions | OT_reactions)[0]

		#rx_cat[to_block] = -1 # TODO: check this
		self.block_reactions_from_idxs(rx_cat)

		costbase = zeros(self._n, )
		costbase[OT_reactions] = om

		print('Step 3 started')
		s1t = time()

		ES_OT = {}


		# def _step_three(rx):
		# 	dep, to_del = self.find_dependent_reactions(rx, constraint, constrainby, costfx, costbase, ntimes, 1e-6)
		# 	ES_OT[rx] = dep[OT_reactions]
		#
		ES_temp = where(ES_reactions)[0]
		if (threads and threads > 1) and (len(ES_temp)/2 > threads):
			res3 = _corda_find_all_dependencies(ES_temp)
		else:
			res3 = list(map(nested_dependent_rxs, ES_temp))



		s3_deps, _ = list(zip(*res3))
		for rx, dep in zip(where(ES_reactions)[0], s3_deps):
			ES_OT[rx] = dep[OT_reactions]

		ES_OT = [ES_OT[k] for k in sorted(ES_OT.keys()) if rx_cat[k] != -1]

		print('\t- Finished in ',str(time()-s1t),'seconds')
		print(pd.Series(rx_cat).value_counts())


		OT_reaction_ids = where(OT_reactions)[0]
		if ES_OT:
			ES_OT = vstack(ES_OT)
			if ES_OT.shape[1] > 0:
				OT_occurrence = apply_along_axis(sum, 0, ES_OT)
				ot_to_es_idx = OT_reaction_ids[OT_occurrence != 0]
				rx_cat[ot_to_es_idx] = 1

		return rx_cat
def straighten_up_character(
        mx: '2D ndarray representing a character image',
        return_angle: 'return the angle instead of transformed matrix' = False
):
    """    Put an inclined symbol in a 2D-ndarray-image straight. 
    Uses eigenvectors to do that.
    Get either the matrix with the straightened up symbol or the angle to use with scipy.ndimage.interpolation.rotate"""

    from itertools import product
    from numpy import ndarray, array, clip, logical_or, c_, cov, argmax, dot, zeros
    from numpy.linalg import eig
    if not (isinstance(mx, ndarray) and mx.ndim == 2):
        raise TypeError("must be a 2D ndarray")

    #make an index array representing the matrix's indeses
    nx = list(product(range(mx.shape[0]), range(
        mx.shape[1])))  # ndarray-indeces  (row,column) format
    nx = array(nx, dtype='i')

    #colour values in the unravelled form (each pocket corresponds to the index in the nx array)
    values = mx.flatten()

    #omit zero values i.e. white pixels
    mask = values > 0
    nx, values = (a[mask] for a in (nx, values))

    #FIND THE CENTER OF THE CHARACTER (not the center of the matrix)
    B = clip(mx, 0, 1).astype(bool)  # boolean matrix denoting coloured pixels
    X = logical_or.reduce(B, axis=0)  # boolean x-axis
    Y = logical_or.reduce(B, axis=1)  # boolean y axis

    #find where the character colour pixels begin and end
    try:
        xstart = X.tolist().index(True)
    except ValueError:
        xstart = 0

    try:
        ystart = Y.tolist().index(True)
    except ValueError:
        ystart = 0

    try:
        xend = (mx.shape[1] - 1) - list(reversed(X)).index(True)
    except ValueError:
        xend = mx.shape[1] - 1

    try:
        yend = (mx.shape[0] - 1) - list(reversed(Y)).index(True)
    except ValueError:
        yend = mx.shape[0] - 1

    x_center = (xend - xstart) // 2 + xstart
    y_center = (yend - ystart) // 2 + ystart

    #convert array-indeces into cartesian coordinates
    xcoords = nx[:, 1] - x_center
    ycoords = -(nx[:, 0] - y_center)
    coords = c_[xcoords, ycoords]

    #get covariance matrix
    Σ = cov(coords.T)  #covariance matrix

    #get the eigenvectors
    λλ, ee = eig(Σ)  # eigenvalues and unit i.e. normalized eigenvectors
    e1, e2 = ee[:, argmax(λλ)], ee[:, int(not bool(argmax(λλ)))]
    e1 = -e1  # change the direction of the vector (arbitrary)
    e2 = -e2

    #get the angle of the eigenvector
    x = e1[0]
    from math import asin, degrees
    angle = degrees(asin(x))
    straighten_up_character.angle = angle
    if return_angle: return angle

    #calculate the projections on the eigenvectors (via dotproduct)
    ycoords = dot(coords, e1)
    xcoords = dot(coords, e2)

    #convert Cartesian coordinates back into array-indeces
    xcoords = xcoords + x_center
    ycoords = -ycoords + y_center
    coords = c_[ycoords, xcoords]
    coords = coords.round()

    #provide for the situation that the new matrix streaches beyond the original one and therefore might have now negative values for array-indeses
    mask = ~logical_or(
        coords[:, 0] < 0, coords[:, 1] <
        0)  #what if some indeces ended up with negative values?...
    coords = coords[mask].astype('uint16')  #eliminate those pixels and indeses
    values = values[mask]

    #make a new matrix and fill the new empty matrix with values
    mx_new = zeros(shape=c_[coords.max(0), mx.shape].max(1), dtype='uint8')
    nx_x, nx_y = coords.T
    mx_new[nx_x, nx_y] = values
    return mx_new
Beispiel #8
0
def equilibria(TempC, Pdbar, pHScale, WhichKs, WhoseKSO4, WhoseKF, TP, TSi, Sal,
        TF, TS):
    """Evaluate all stoichiometric equilibrium constants, converted to the
    chosen pH scale, and corrected for pressure.

    Inputs must first be conditioned with inputs().

    This finds the Constants of the CO2 system in seawater or freshwater,
    corrects them for pressure, and reports them on the chosen pH scale.
    The process is as follows: the Constants (except KS, KF which stay on the
    free scale - these are only corrected for pressure) are:
          1) evaluated as they are given in the literature,
          2) converted to the SWS scale in mol/kg-SW or to the NBS scale,
          3) corrected for pressure,
          4) converted to the SWS pH scale in mol/kg-SW,
          5) converted to the chosen pH scale.

    Based on a subset of Constants, version 04.01, 10-13-97, by Ernie Lewis.
    """
    # PROGRAMMER'S NOTE: all logs are log base e
    # PROGRAMMER'S NOTE: all Constants are converted to the pH scale
    #     pHScale# (the chosen one) in units of mol/kg-SW
    #     except KS and KF are on the free scale
    #     and KW is in units of (mol/kg-SW)^2

    TempK, Pbar, RT = units(TempC, Pdbar)

    # Calculate K0 (Henry's constant for CO2)
    K0 = eq.kCO2_W74(TempK, Sal)

    # Calculate KS (bisulfate ion dissociation constant)
    KS = full_like(TempK, nan)
    F = WhoseKSO4==1
    if any(F):
        KS[F] = eq.kHSO4_FREE_D90a(TempK[F], Sal[F])
    F = WhoseKSO4==2
    if any(F):
        KS[F] = eq.kHSO4_FREE_KRCB77(TempK[F], Sal[F])

    # Calculate KF (hydrogen fluoride dissociation constant)
    KF = full_like(TempC, nan)
    F = WhoseKF==1
    if any(F):
        KF[F] = eq.kHF_FREE_DR79(TempK[F], Sal[F])
    F = WhoseKF==2
    if any(F):
        KF[F] = eq.kHF_FREE_PF87(TempK[F], Sal[F])

    # Calculate pH scale conversion factors - these are NOT pressure-corrected
    SWStoTOT = convert.sws2tot(TS, KS, TF, KF)
    # Calculate fH
    fH = full_like(TempC, nan)
    # Use GEOSECS's value for cases 1-6 to convert pH scales
    F = WhichKs==8
    if any(F):
        fH[F] = 1.0 # this shouldn't occur in the program for this case
    F = WhichKs==7
    if any(F):
        fH[F] = convert.fH_PTBO87(TempK[F], Sal[F])
    F = logical_and(WhichKs!=7, WhichKs!=8)
    if any(F):
        fH[F] = convert.fH_TWB82(TempK[F], Sal[F])

    # Calculate boric acid dissociation constant (KB)
    KB = full_like(TempC, nan)
    F = WhichKs==8 # Pure water case
    if any(F):
        KB[F] = 0.0
    F = logical_or(WhichKs==6, WhichKs==7)
    if any(F):
        KB[F] = eq.kBOH3_NBS_LTB69(TempK[F], Sal[F])
        KB[F] /= fH[F] # Convert NBS to SWS
    F = logical_and.reduce((WhichKs!=6, WhichKs!=7, WhichKs!=8))
    if any(F):
        KB[F] = eq.kBOH3_TOT_D90b(TempK[F], Sal[F])
        KB[F] /= SWStoTOT[F] # Convert TOT to SWS

    # Calculate water dissociation constant (KW)
    KW = full_like(TempC, nan)
    F = WhichKs==7
    if any(F):
        KW[F] = eq.kH2O_SWS_M79(TempK[F], Sal[F])
    F = WhichKs==8
    if any(F):
        KW[F] = eq.kH2O_SWS_HO58_M79(TempK[F], Sal[F])
    F = logical_and.reduce((WhichKs!=6, WhichKs!=7, WhichKs!=8))
    if any(F):
        KW[F] = eq.kH2O_SWS_M95(TempK[F], Sal[F])
    # KW is on the SWS pH scale in (mol/kg-SW)**2
    F = WhichKs==6
    if any(F):
        KW[F] = 0 # GEOSECS doesn't include OH effects

    # Calculate phosphate and silicate dissociation constants
    KP1 = full_like(TempC, nan)
    KP2 = full_like(TempC, nan)
    KP3 = full_like(TempC, nan)
    KSi = full_like(TempC, nan)
    F = WhichKs==7
    if any(F):
        KP1[F], KP2[F], KP3[F] = eq.kH3PO4_NBS_KP67(TempK[F], Sal[F])
        # KP1 is already on SWS!
        KP2[F] /= fH[F] # Convert NBS to SWS
        KP3[F] /= fH[F] # Convert NBS to SWS
        KSi[F] = eq.kSi_NBS_SMB64(TempK[F], Sal[F])
        KSi[F] /= fH[F] # Convert NBS to SWS
    F = logical_or(WhichKs==6, WhichKs==8)
    if any(F):
        # Neither the GEOSECS choice nor the freshwater choice
        # include contributions from phosphate or silicate.
        KP1[F] = 0.0
        KP2[F] = 0.0
        KP3[F] = 0.0
        KSi[F] = 0.0
    F = logical_and.reduce((WhichKs!=6, WhichKs!=7, WhichKs!=8))
    if any(F):
        KP1[F], KP2[F], KP3[F] = eq.kH3PO4_SWS_YM95(TempK[F], Sal[F])
        KSi[F] = eq.kSi_SWS_YM95(TempK[F], Sal[F])

    # Calculate carbonic acid dissociation constants (K1 and K2)
    K1 = full_like(TempC, nan)
    K2 = full_like(TempC, nan)
    F = WhichKs==1
    if any(F):
        K1[F], K2[F] = eq.kH2CO3_TOT_RRV93(TempK[F], Sal[F])
        K1[F] /= SWStoTOT[F] # Convert TOT to SWS
        K2[F] /= SWStoTOT[F] # Convert TOT to SWS
    F = WhichKs==2
    if any(F):
        K1[F], K2[F] = eq.kH2CO3_SWS_GP89(TempK[F], Sal[F])
    F = WhichKs==3
    if any(F):
        K1[F], K2[F] = eq.kH2CO3_SWS_H73_DM87(TempK[F], Sal[F])
    F = WhichKs==4
    if any(F):
        K1[F], K2[F] = eq.kH2CO3_SWS_MCHP73_DM87(TempK[F], Sal[F])
    F = WhichKs==5
    if any(F):
        K1[F], K2[F] = eq.kH2CO3_SWS_HM_DM87(TempK[F], Sal[F])
    F = logical_or(WhichKs==6, WhichKs==7)
    if any(F):
        K1[F], K2[F] = eq.kH2CO3_NBS_MCHP73(TempK[F], Sal[F])
        K1[F] /= fH[F] # Convert NBS to SWS
        K2[F] /= fH[F] # Convert NBS to SWS
    F = WhichKs==8
    if any(F):
        K1[F], K2[F] = eq.kH2CO3_SWS_M79(TempK[F], Sal[F])
    F = WhichKs==9
    if any(F):
        K1[F], K2[F] = eq.kH2CO3_NBS_CW98(TempK[F], Sal[F])
        K1[F] /= fH[F] # Convert NBS to SWS
        K2[F] /= fH[F] # Convert NBS to SWS
    F = WhichKs==10
    if any(F):
        K1[F], K2[F] = eq.kH2CO3_TOT_LDK00(TempK[F], Sal[F])
        K1[F] /= SWStoTOT[F] # Convert TOT to SWS
        K2[F] /= SWStoTOT[F] # Convert TOT to SWS
    F = WhichKs==11
    if any(F):
        K1[F], K2[F] = eq.kH2CO3_SWS_MM02(TempK[F], Sal[F])
    F = WhichKs==12
    if any(F):
        K1[F], K2[F] = eq.kH2CO3_SWS_MPL02(TempK[F], Sal[F])
    F = WhichKs==13
    if any(F):
        K1[F], K2[F] = eq.kH2CO3_SWS_MGH06(TempK[F], Sal[F])
    F = WhichKs==14
    if any(F):
        K1[F], K2[F] = eq.kH2CO3_SWS_M10(TempK[F], Sal[F])
    F = WhichKs==15
    if any(F):
        K1[F], K2[F] = eq.kH2CO3_SWS_WMW14(TempK[F], Sal[F])

    # From CO2SYS_v1_21.m: calculate KH2S and KNH3
    KH2S = full_like(TempC, nan)
    KNH3 = full_like(TempC, nan)
    F = logical_or.reduce((WhichKs==6, WhichKs==7, WhichKs==8))
    # Contributions from NH3 and H2S not included for these options.
    if any(F):
        KH2S[F] = 0.0
        KNH3[F] = 0.0
    F = logical_and.reduce((WhichKs!=6, WhichKs!=7, WhichKs!=8))
    if any(F):
        KH2S[F] = eq.kH2S_TOT_YM95(TempK[F], Sal[F])
        KNH3[F] = eq.kNH3_TOT_CW95(TempK[F], Sal[F])
        KH2S[F] /= SWStoTOT[F] # Convert TOT to SWS
        KNH3[F] /= SWStoTOT[F] # Convert TOT to SWS

#****************************************************************************
# Correct dissociation constants for pressure
# Currently: For WhichKs# = 1 to 7, all Ks (except KF and KS, which are on
#       the free scale) are on the SWS scale.
#       For WhichKs# = 6, KW set to 0, KP1, KP2, KP3, KSi don't matter.
#       For WhichKs# = 8, K1, K2, and KW are on the "pH" pH scale
#       (the pH scales are the same in this case); the other Ks don't
#       matter.
#
# No salinity dependence is given for the pressure coefficients here.
# It is assumed that the salinity is at or very near Sali = 35.
# These are valid for the SWS pH scale, but the difference between this and
# the total only yields a difference of .004 pH units at 1000 bars, much
# less than the uncertainties in the values.
#****************************************************************************
# The sources used are:
# Millero, 1995:
#       Millero, F. J., Thermodynamics of the carbon dioxide system in the
#       oceans, Geochemica et Cosmochemica Acta 59:661-677, 1995.
#       See table 9 and eqs. 90-92, p. 675.
#       TYPO: a factor of 10^3 was left out of the definition of Kappa
#       TYPO: the value of R given is incorrect with the wrong units
#       TYPO: the values of the a's for H2S and H2O are from the 1983
#                values for fresh water
#       TYPO: the value of a1 for B(OH)3 should be +.1622
#        Table 9 on p. 675 has no values for Si.
#       There are a variety of other typos in Table 9 on p. 675.
#       There are other typos in the paper, and most of the check values
#       given don't check.
# Millero, 1992:
#       Millero, Frank J., and Sohn, Mary L., Chemical Oceanography,
#       CRC Press, 1992. See chapter 6.
#       TYPO: this chapter has numerous typos (eqs. 36, 52, 56, 65, 72,
#               79, and 96 have typos).
# Millero, 1983:
#       Millero, Frank J., Influence of pressure on chemical processes in
#       the sea. Chapter 43 in Chemical Oceanography, eds. Riley, J. P. and
#       Chester, R., Academic Press, 1983.
#       TYPO: p. 51, eq. 94: the value -26.69 should be -25.59
#       TYPO: p. 51, eq. 95: the term .1700t should be .0800t
#       these two are necessary to match the values given in Table 43.24
# Millero, 1979:
#       Millero, F. J., The thermodynamics of the carbon dioxide system
#       in seawater, Geochemica et Cosmochemica Acta 43:1651-1661, 1979.
#       See table 5 and eqs. 7, 7a, 7b on pp. 1656-1657.
# Takahashi et al, in GEOSECS Pacific Expedition, v. 3, 1982.
#       TYPO: the pressure dependence of K2 should have a 16.4, not 26.4
#       This matches the GEOSECS results and is in Edmond and Gieskes.
# Culberson, C. H. and Pytkowicz, R. M., Effect of pressure on carbonic acid,
#       boric acid, and the pH of seawater, Limnology and Oceanography
#       13:403-417, 1968.
# Edmond, John M. and Gieskes, J. M. T. M., The calculation of the degree of
#       seawater with respect to calcium carbonate under in situ conditions,
#       Geochemica et Cosmochemica Acta, 34:1261-1291, 1970.
#****************************************************************************
# These references often disagree and give different fits for the same thing.
# They are not always just an update either; that is, Millero, 1995 may agree
#       with Millero, 1979, but differ from Millero, 1983.
# For WhichKs# = 7 (Peng choice) I used the same factors for KW, KP1, KP2,
#       KP3, and KSi as for the other cases. Peng et al didn't consider the
#       case of P different from 0. GEOSECS did consider pressure, but didn't
#       include Phos, Si, or OH, so including the factors here won't matter.
# For WhichKs# = 8 (freshwater) the values are from Millero, 1983 (for K1, K2,
#       and KW). The other aren't used (TB = TS = TF = TP = TSi = 0.), so
#       including the factors won't matter.
#****************************************************************************
#       deltaVs are in cm3/mole
#       Kappas are in cm3/mole/bar
#****************************************************************************

    # Correct K1, K2 and KB for pressure:
    deltaV = full_like(TempC, nan)
    Kappa = full_like(TempC, nan)
    lnK1fac = full_like(TempC, nan)
    lnK2fac = full_like(TempC, nan)
    lnKBfac = full_like(TempC, nan)
    F = WhichKs==8
    if any(F):
        # Pressure effects on K1 in freshwater: this is from Millero, 1983.
        deltaV[F]  = -30.54 + 0.1849 *TempC[F] - 0.0023366*TempC[F]**2
        Kappa[F]   = (-6.22 + 0.1368 *TempC[F] - 0.001233 *TempC[F]**2)/1000
        lnK1fac[F] = (-deltaV[F] + 0.5*Kappa[F]*Pbar[F])*Pbar[F]/RT[F]
        # Pressure effects on K2 in freshwater: this is from Millero, 1983.
        deltaV[F]  = -29.81 + 0.115*TempC[F] - 0.001816*TempC[F]**2
        Kappa[F]   = (-5.74 + 0.093*TempC[F] - 0.001896*TempC[F]**2)/1000
        lnK2fac[F] = (-deltaV[F] + 0.5*Kappa[F]*Pbar[F])*Pbar[F]/RT[F]
        lnKBfac[F] = 0 #; this doesn't matter since TB = 0 for this case
    F = logical_or(WhichKs==6, WhichKs==7)
    if any(F):
        # GEOSECS Pressure Effects On K1, K2, KB (on the NBS scale)
        # Takahashi et al, GEOSECS Pacific Expedition v. 3, 1982 quotes
        # Culberson and Pytkowicz, L and O 13:403-417, 1968:
        # but the fits are the same as those in
        # Edmond and Gieskes, GCA, 34:1261-1291, 1970
        # who in turn quote Li, personal communication
        lnK1fac[F] = (24.2 - 0.085*TempC[F])*Pbar[F]/RT[F]
        lnK2fac[F] = (16.4 - 0.04 *TempC[F])*Pbar[F]/RT[F]
        #               Takahashi et al had 26.4, but 16.4 is from Edmond and Gieskes
        #               and matches the GEOSECS results
        lnKBfac[F] = (27.5 - 0.095*TempC[F])*Pbar[F]/RT[F]
    F=logical_and.reduce((WhichKs!=6, WhichKs!=7, WhichKs!=8))
    if any(F):
        #***PressureEffectsOnK1:
        #               These are from Millero, 1995.
        #               They are the same as Millero, 1979 and Millero, 1992.
        #               They are from data of Culberson and Pytkowicz, 1968.
        deltaV[F]  = -25.5 + 0.1271*TempC[F]
        #                 'deltaV = deltaV - .151*(Sali - 34.8); # Millero, 1979
        Kappa[F]   = (-3.08 + 0.0877*TempC[F])/1000
        #                 'Kappa = Kappa  - .578*(Sali - 34.8)/1000.; # Millero, 1979
        lnK1fac[F] = (-deltaV[F] + 0.5*Kappa[F]*Pbar[F])*Pbar[F]/RT[F]
        #               The fits given in Millero, 1983 are somewhat different.

        #***PressureEffectsOnK2:
        #               These are from Millero, 1995.
        #               They are the same as Millero, 1979 and Millero, 1992.
        #               They are from data of Culberson and Pytkowicz, 1968.
        deltaV[F]  = -15.82 - 0.0219*TempC[F]
        #                  'deltaV = deltaV + .321*(Sali - 34.8); # Millero, 1979
        Kappa[F]   = (1.13 - 0.1475*TempC[F])/1000
        #                 'Kappa = Kappa - .314*(Sali - 34.8)/1000: # Millero, 1979
        lnK2fac[F] = (-deltaV[F] + 0.5*Kappa[F]*Pbar[F])*Pbar[F]/RT[F]
        #               The fit given in Millero, 1983 is different.
        #               Not by a lot for deltaV, but by much for Kappa. #

        #***PressureEffectsOnKB:
        #               This is from Millero, 1979.
        #               It is from data of Culberson and Pytkowicz, 1968.
        deltaV[F]  = -29.48 + 0.1622*TempC[F] - 0.002608*TempC[F]**2
        #               Millero, 1983 has:
        #                 'deltaV = -28.56 + .1211*TempCi - .000321*TempCi*TempCi
        #               Millero, 1992 has:
        #                 'deltaV = -29.48 + .1622*TempCi + .295*(Sali - 34.8)
        #               Millero, 1995 has:
        #                 'deltaV = -29.48 - .1622*TempCi - .002608*TempCi*TempCi
        #                 'deltaV = deltaV + .295*(Sali - 34.8); # Millero, 1979
        Kappa[F]   = -2.84/1000 # Millero, 1979
        #               Millero, 1992 and Millero, 1995 also have this.
        #                 'Kappa = Kappa + .354*(Sali - 34.8)/1000: # Millero,1979
        #               Millero, 1983 has:
        #                 'Kappa = (-3 + .0427*TempCi)/1000
        lnKBfac[F] = (-deltaV[F] + 0.5*Kappa[F]*Pbar[F])*Pbar[F]/RT[F]

    # CorrectKWForPressure:
    lnKWfac = full_like(TempC, nan)
    F=(WhichKs==8)
    if any(F):
        # PressureEffectsOnKWinFreshWater:
        #               This is from Millero, 1983.
        deltaV[F]  =  -25.6 + 0.2324*TempC[F] - 0.0036246*TempC[F]**2
        Kappa[F]   = (-7.33 + 0.1368*TempC[F] - 0.001233 *TempC[F]**2)/1000
        lnKWfac[F] = (-deltaV[F] + 0.5*Kappa[F]*Pbar[F])*Pbar[F]/RT[F]

        #               NOTE the temperature dependence of KappaK1 and KappaKW
        #               for fresh water in Millero, 1983 are the same.
    F=(WhichKs!=8)
    if any(F):
        # GEOSECS doesn't include OH term, so this won't matter.
        # Peng et al didn't include pressure, but here I assume that the KW correction
        #       is the same as for the other seawater cases.
        # PressureEffectsOnKW:
        #               This is from Millero, 1983 and his programs CO2ROY(T).BAS.
        deltaV[F]  = -20.02 + 0.1119*TempC[F] - 0.001409*TempC[F]**2
        #               Millero, 1992 and Millero, 1995 have:
        Kappa[F]   = (-5.13 + 0.0794*TempC[F])/1000 # Millero, 1983
        #               Millero, 1995 has this too, but Millero, 1992 is different.
        lnKWfac[F] = (-deltaV[F] + 0.5*Kappa[F]*Pbar[F])*Pbar[F]/RT[F]
        #               Millero, 1979 does not list values for these.

    # PressureEffectsOnKF:
    #       This is from Millero, 1995, which is the same as Millero, 1983.
    #       It is assumed that KF is on the free pH scale.
    deltaV = -9.78 - 0.009*TempC - 0.000942*TempC**2
    Kappa = (-3.91 + 0.054*TempC)/1000
    lnKFfac = (-deltaV + 0.5*Kappa*Pbar)*Pbar/RT
    # PressureEffectsOnKS:
    #       This is from Millero, 1995, which is the same as Millero, 1983.
    #       It is assumed that KS is on the free pH scale.
    deltaV = -18.03 + 0.0466*TempC + 0.000316*TempC**2
    Kappa = (-4.53 + 0.09*TempC)/1000
    lnKSfac = (-deltaV + 0.5*Kappa*Pbar)*Pbar/RT

    # CorrectKP1KP2KP3KSiForPressure:
    # These corrections don't matter for the GEOSECS choice (WhichKs# = 6) and
    #       the freshwater choice (WhichKs# = 8). For the Peng choice I assume
    #       that they are the same as for the other choices (WhichKs# = 1 to 5).
    # The corrections for KP1, KP2, and KP3 are from Millero, 1995, which are the
    #       same as Millero, 1983.
    # PressureEffectsOnKP1:
    deltaV = -14.51 + 0.1211*TempC - 0.000321*TempC**2
    Kappa  = (-2.67 + 0.0427*TempC)/1000
    lnKP1fac = (-deltaV + 0.5*Kappa*Pbar)*Pbar/RT
    # PressureEffectsOnKP2:
    deltaV = -23.12 + 0.1758*TempC - 0.002647*TempC**2
    Kappa  = (-5.15 + 0.09  *TempC)/1000
    lnKP2fac = (-deltaV + 0.5*Kappa*Pbar)*Pbar/RT
    # PressureEffectsOnKP3:
    deltaV = -26.57 + 0.202 *TempC - 0.003042*TempC**2
    Kappa  = (-4.08 + 0.0714*TempC)/1000
    lnKP3fac = (-deltaV + 0.5*Kappa*Pbar)*Pbar/RT
    # PressureEffectsOnKSi:
    #  The only mention of this is Millero, 1995 where it is stated that the
    #    values have been estimated from the values of boric acid. HOWEVER,
    #    there is no listing of the values in the table.
    #    I used the values for boric acid from above.
    deltaV = -29.48 + 0.1622*TempC - 0.002608*TempC**2
    Kappa  = -2.84/1000
    lnKSifac = (-deltaV + 0.5*Kappa*Pbar)*Pbar/RT

    # CorrectKNH3KH2SForPressure:
    # The corrections are from Millero, 1995, which are the
    #       same as Millero, 1983.
    # PressureEffectsOnKNH3:
    deltaV = -26.43 + 0.0889*TempC - 0.000905*TempC**2
    Kappa = (-5.03 + 0.0814*TempC)/1000
    lnKNH3fac = (-deltaV + 0.5*Kappa*Pbar)*Pbar/RT
    # PressureEffectsOnKH2S:
    # Millero 1995 gives values for deltaV in fresh water instead of SW.
    # Millero 1995 gives -b0 as -2.89 instead of 2.89
    # Millero 1983 is correct for both
    deltaV = -11.07 - 0.009*TempC - 0.000942*TempC**2
    Kappa = (-2.89 + 0.054*TempC)/1000
    lnKH2Sfac = (-deltaV + 0.5*Kappa*Pbar)*Pbar/RT

    # CorrectKsForPressureHere:
    K1 *= exp(lnK1fac)
    K2 *= exp(lnK2fac)
    KW *= exp(lnKWfac)
    KB *= exp(lnKBfac)
    KF *= exp(lnKFfac)
    KS *= exp(lnKSfac)
    KP1 *= exp(lnKP1fac)
    KP2 *= exp(lnKP2fac)
    KP3 *= exp(lnKP3fac)
    KSi *= exp(lnKSifac)
    KNH3 *= exp(lnKNH3fac)
    KH2S *= exp(lnKH2Sfac)

    # CorrectpHScaleConversionsForPressure:
    # fH has been assumed to be independent of pressure.
    SWStoTOT = convert.sws2tot(TS, KS, TF, KF)
    FREEtoTOT = convert.free2tot(TS, KS)

    #  The values KS and KF are already pressure-corrected, so the pH scale
    #  conversions are now valid at pressure.

    # Find pH scale conversion factor: this is the scale they will be put on
    pHfactor = full_like(TempC, nan)
    F = pHScale==1 # Total
    pHfactor[F] = SWStoTOT[F]
    F = pHScale==2 # SWS, they are all on this now
    pHfactor[F] = 1.0
    F = pHScale==3 # pHfree
    pHfactor[F] = SWStoTOT[F]/FREEtoTOT[F]
    F = pHScale==4 # pHNBS
    pHfactor[F] = fH[F]

    # Convert from SWS pH scale to chosen scale
    K1 *= pHfactor
    K2 *= pHfactor
    KW *= pHfactor
    KB *= pHfactor
    KP1 *= pHfactor
    KP2 *= pHfactor
    KP3 *= pHfactor
    KSi *= pHfactor
    KNH3 *= pHfactor
    KH2S *= pHfactor

    return K0, K1, K2, KW, KB, KF, KS, KP1, KP2, KP3, KSi, KNH3, KH2S, fH
def intersect(a, b, axis=2):
    from numpy import logical_and, logical_or
    return unique(a[logical_or.reduce(logical_and.reduce(a == b[:,None], axis=axis))])